Edycja pliku zapisanego w formacie UTF-8 without BOM

Edycja pliku zapisanego w formacie UTF-8 without BOM
AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0

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

Kopiuj
<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: flowCRANE
pelsta
  • Rejestracja:prawie 19 lat
  • Ostatnio:19 dni
  • Postów:819
1

Plik Utf8 należałoby wczytać do zmiennej string, przekonwertować do Ansii funkcją Utf8ToAnsi, dokonać potrzebnych edycji, ponownie przekonwertować do Utf8 funkcją AnsiToUtf8 i zapisać na dysk.

Ale ten plik (index.txt) jest kodowany w ANSI tyle, że zapisany w formacie UNIX (znaki końca linii to #10 zamiast #13#10)

AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0

Ciekawe dlaczego notepad++ wykrywa go jako UTF-8 without BOM?

edytowany 2x, ostatnio: flowCRANE
pelsta
  • Rejestracja:prawie 19 lat
  • Ostatnio:19 dni
  • Postów:819
0

Nie wiem, której wersji npp używasz. Ja zatrzymałem się na v7.5.9 ponieważ stwierdziłem, że nowsze nie radzą sobie dobrze z automatycznym wykrywaniem kodowania.
Jakieś dziwne znaki widzę na końcu pliku w sekcji ExtraDataList.

edytowany 1x, ostatnio: pelsta
AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0
pelsta napisał(a):

Nie wiem, której wersji npp używasz. Ja zatrzymałem się na v7.5.9 ponieważ stwierdziłem, że nowsze nie radzą sobie dobrze z automatycznym wykrywaniem kodowania.

6.3

AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0

Te dziwne znaki muszą tam być! Gdy edytuje ten plik to one mi znikają!

Prosty przykład

Kopiuj
StringList:=TStringList.Create;
  StringList.LoadFromFile('index.txt');
  StringList.SaveToFile('newindex.txt');

Oryginalny plik
title

nowy plik
title

Nie dość że "dziwne znaki" znikają to jeszcze brakuje paru lini na końcu. WTF?!

edytowany 2x, ostatnio: Atak_Snajpera
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
0

Znaki kontrolne zapisywane w plikach tekstowych powinny być escapowane, tak aby nie wpływały one na metody czytające ciągi znaków. A tu drugim znakiem jest NULL i do widzenia – się nie dziw że ucina.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0

Dobra. To w praktyce jak zapisać tak aby nic nie ucinało?

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
0

Escape character – poczytaj, znajdziesz tam dużo przykładów. Sprawdź też czy masz dostęp do metod, które pozwalają formatować takie ciągi (kodować i odkodowywać). Jeśli nie to będziesz musiał sobie takie napisać.

W razie czego zamiast escapowania, możesz konwertować ciąg na jakiś Base64 lub coś podobnego – byle ciąg wyjściowy nie zawierał surowych znaków kontrolnych.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0

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

abrakadaber
abrakadaber
TO NIE JEST PLIK TEKSTOWY!!! Jakby był to plik tekstowy to by to działało. DO jest jakiś miks tekstu i raw data a tego się w ten sposób nie robi. Jak chcesz grzebać w takich plikach to użyj TFileStream i pochodnych
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
0

No jak się surowe NULLe pakuje do tekstowego pliku to nie dziwne, że API się sypie.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
FL4RE
  • Rejestracja:prawie 6 lat
  • Ostatnio:12 miesięcy
  • Postów:21
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

pelsta
  • Rejestracja:prawie 19 lat
  • Ostatnio:19 dni
  • Postów:819
0

Faktycznie. Plik należy potraktować jako binarny.

Kopiuj
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);
AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
0

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

Kopiuj
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: flowCRANE
Marius.Maximus
  • Rejestracja:ponad 14 lat
  • Ostatnio:3 minuty
  • Postów:2068
0

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


--
Nie przyjmuję reklamacji za moje rady, używasz na własną odpowiedzialność.
Programowanie bez formatowania to jak chodzenie ze spodniami spuszczonymi na kostki. Owszem da się ale po pierwsze nie wygodne, po drugie nieprzyzwoicie wygląda.
Przed zaczęciem nowego wątku przeczytam problem XY
AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
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
FL4RE
  • Rejestracja:prawie 6 lat
  • Ostatnio:12 miesięcy
  • Postów:21
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

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:31 minut
0

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

AS
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:48
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/L-SMASH-Works/tree/master/AviSynth )

KR
  • Rejestracja:ponad 6 lat
  • Ostatnio:około rok
  • Postów:174
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:)

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)