Edycja pliku zapisanego w formacie UTF-8 without BOM

Odpowiedz Nowy wątek
2019-07-28 13:02
0

Mam taki pliczek tekstowy ( https://www.mediafire.com/file/2mt9bkwbefa1mib/index.txt/file )
Chcę podmienić linię

<InputFilePath>\\XEON-PC\RipBot264temp\job1\video.mkv</InputFilePath>

i następnie zapisać.

Problem jest taki że nie jest to zwykłe kodowanie ANSI tylko UTF-8 without BOM. Jak wygląda procedura obróbki takich plików w takim np. TStringList?

Mam Delphi 10.3 oraz Delphi 7 z zainstalowanym komponentem TNT ( https://github.com/rofl0r/TntUnicode ).

edytowany 1x, ostatnio: furious programming, 2019-07-28 14:50

Pozostało 580 znaków

2019-07-28 18:01
0
Atak_Snajpera napisał(a):

Ja pierdziele! Tyle roboty aby podmienić jedną głupią linie w pliku tekstowym...

Ja w takim wypadku, gdzie trzeba patchować plik binarny (a tak trzeba rozważyć ten plik), ładowałem pliczek do strumienia a nastepnie kopiowałem pamięć do AnsiStringa. Jak będziesz miał to w tej zmiennej to robisz sobie StringReplace i nastepnie zapisujesz do strumienia i do pliczku. Niestety nie poratuje Cię tym kodem, bo go już nie mam

Pozostało 580 znaków

2019-07-29 08:48
0

Faktycznie. Plik należy potraktować jako binarny.

function ReadString(fn:string):string;
var
  f:file of Char;
  fs:Integer;
begin
  AssignFile(f,fn);
  Reset(f);
  fs:=FileSize(f);
  SetLength(Result,fs);
  BlockRead(f,Result[1],fs);
  CloseFile(f);
end;

procedure WriteString(fn,s:string);
var
  f:file of Char;
  fs:Integer;
begin
  AssignFile(f,fn);
  Rewrite(f);
  fs:=Length(s);
  BlockWrite(f,s[1],fs);
  CloseFile(f);
end;

...

var s1,s2:string;
  s1:=ReadString('index.txt');
  s2:=StringReplace(s1,'<InputFilePath>\\XEON-PC\RipBot264temp\job1\video.mkv</InputFilePath>','<InputFilePath>nowy wpis</InputFilePath>',[]);
  WriteString('index1.txt',s2);

Pozostało 580 znaków

2019-07-29 12:26
0

Ostatecznie wczoraj poradziłem sobie z tym problemem w trochę bardziej skomplikowany sposób niż to zaproponował pelsta.

function TActivationThread.ModifyInputFilePathInIndexFile(InputFile:string):boolean;
var StringList:TStringList;
    SourceFileHandle,TargetFileHandle:THandle;
    SourceStream,TargetStream:TFileStream;
    DataArray:array of byte;
    PositionInFile,NullPos:int64;
    PositionInArray:integer;
    BytesRead,BytesWritten,x:integer;
    TextLine,CurrentDomainName,CurrentJob,OutputFile:string;

    function FindNullPos(var Buffer:array of byte):integer;
    var x:integer;
    begin
      Result:=-1;
      for x:=0 to Length(Buffer)-1 do
      begin
        if Buffer[x]=0 then
        begin
          Result:=x;
          exit;
        end;
      end;
    end;

begin

  Result:=false;
  if FileExists(InputFile)=false then exit;

  CurrentDomainName:=form1.JvComputerInfoEx1.Identification.LocalComputerName;
  CurrentJob:=Copy(CurrentJobFolder,Pos('job',CurrentJobFolder),MaxInt);
  OutputFile:=CurrentJobFolder+'\video.mkv.lwi.tmp';

  StringList:=TStringList.Create;
  StringList.LoadFromFile(InputFile);

  for x:=0 to StringList.Count-1 do
  begin
    TextLine:=StringList.Strings[x];
    if Pos('<InputFilePath>',TextLine)>0 then
    begin
      StringList.Strings[x]:='<InputFilePath>\\'+CurrentDomainName+'\RipBot264temp\'+CurrentJob+'\video.mkv</InputFilePath>';
      break;
    end;
  end;

  StringList.SaveToFile(OutputFile);
  StringList.Free;

  SourceFileHandle:=CreateFile(PChar(InputFile), GENERIC_READ, FILE_SHARE_READ, nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  TargetFileHandle:=CreateFile(PChar(OutputFile), GENERIC_WRITE, FILE_SHARE_WRITE, nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  if SourceFileHandle=INVALID_HANDLE_VALUE then exit;

  SourceStream:=TFileStream.Create(SourceFileHandle);
  TargetStream:=TFileStream.Create(TargetFileHandle);
  TargetStream.Seek(0,soFromEnd);

  SetLength(DataArray,16777216);
  try

    repeat
      PositionInFile:=SourceStream.Position;
      BytesRead:=SourceStream.Read(DataArray[0],Length(DataArray));

      PositionInArray:=FindNullPos(DataArray);
      if PositionInArray>-1 then
      begin
        NullPos:=PositionInFile+PositionInArray;
        SourceStream.Seek(NullPos,soBeginning);

        repeat
          BytesRead:=SourceStream.Read(DataArray[0],Length(DataArray));
          BytesWritten:=TargetStream.Write(DataArray[0],BytesRead);
        until (BytesRead=0) or (BytesWritten=0);

      end;

    until (BytesRead=0) or (BytesWritten=0);

  finally
    SourceStream.Free;
    TargetStream.Free;

    CloseHandle(SourceFileHandle);
    CloseHandle(TargetFileHandle);

    Result:=CopyFile(PChar(OutputFile),PChar(CurrentJobFolder+'\video.mkv.lwi'),false);
    DeleteFile(OutputFile);
  end;

end;
edytowany 1x, ostatnio: furious programming, 2019-07-29 13:54

Pozostało 580 znaków

2019-07-29 14:22
0

Jakoś strasznie dużo kodu jak na tak prostą czynność


Nie przyjmuję reklamacji za moje rady, używasz na własną odpowiedzialność

Pozostało 580 znaków

2019-07-29 15:31
0

Tak sobie wczoraj wykombinowałem że jeśli TStringList mi ucina wszystko od bajtu 0 to sobie dokleję resztę strumieniami.

edytowany 1x, ostatnio: Atak_Snajpera, 2019-07-29 15:36

Pozostało 580 znaków

2019-07-29 15:56
0
Atak_Snajpera napisał(a):

Tak sobie wczoraj wykombinowałem że jeśli TStringList mi ucina wszystko od bajtu 0 to sobie dokleję resztę strumieniami.

Proponuje użyć kodu @pelsta

Pozostało 580 znaków

2019-07-29 17:03
0

@Atak_Snajpera a masz wpływ na format tego pliku? bo jest źle pomyślany.

Pozostało 580 znaków

2019-07-29 17:20
0
Azarien napisał(a):

@Atak_Snajpera a masz wpływ na format tego pliku? bo jest źle pomyślany.

Nie, nie mam. Taki plik generuje indexer L-SMASH ( https://github.com/VFR-maniac[...]SH-Works/tree/master/AviSynth )

Pozostało 580 znaków

2019-07-30 13:07
0

Załadowałem ten plik do tstringlist ale we freepascalu (lazarus) i wszystko działa ok, nie trzeba dodatkowych funkcji do formatowania stringów. Nic się nie usuwa:)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0