Seite 2 von 2

Re: Zeilen txt löschen

Verfasst: 30.08.2017 22:05
von Fanpost
@GPI

Die Zeilen in der TXT sehen z.B. wie folgt aus und es sind max 189 Zeilen vorhanden:

<g1#1#1#1#00001.bmp><t280#460#120#arial#NI233><t280#620#120#arial#SW: 01.02.00><t280#760#160B#arial#Serien - Nr: 00001>
<g1#1#1#1#00002.bmp><t280#460#120#arial#NI233><t280#620#120#arial#SW: 01.02.00><t280#760#160B#arial#Serien - Nr: 00002>
<g1#1#1#1#00003.bmp><t280#460#120#arial#NI233><t280#620#120#arial#SW: 01.02.00><t280#760#160B#arial#Serien - Nr: 00003>
.
<g1#1#1#1#00189.bmp><t280#460#120#arial#NI233><t280#620#120#arial#SW: 01.02.00><t280#760#160B#arial#Serien - Nr: 00189>

Es handelt sich um Steuerzeichen inkl. Text für ein Druckprogramm. Sollten z.B. 10 Zeilen falsch erstellt worden sein, so möchte ich diese löschen.

Re: Zeilen txt löschen

Verfasst: 30.08.2017 22:07
von Mijikai
Hab mal was geschrieben :)
Index = Anzahl von #CRLF$ ausgehend vom Ende der Datei!

Bin davon ausgegangen das der Text in Ascii vorliegt!

Code: Alles auswählen

Procedure.i CutFilePart(File.s,Index.i)
  Protected FileSize.i, Count.i, Sig.w
  Protected FileHandle.i = OpenFile(#PB_Any,File)
  If FileHandle
    FileSize = Lof(FileHandle) - 1
    While FileSize
      FileSize - 1
      If FileSize < 0
        FileSize = 0
      EndIf
      FileSeek(FileHandle,FileSize)
      If ReadData(FileHandle,@Sig,2)
        If Sig = 2573
          Count + 1
          If Count = Index
            TruncateFile(FileHandle)
            CloseFile(FileHandle)
            ProcedureReturn #True
          EndIf
        EndIf
      Else
        Break
      EndIf
    Wend
    CloseFile(FileHandle)
  EndIf
EndProcedure

Re: Zeilen txt löschen

Verfasst: 30.08.2017 22:59
von NicTheQuick
Meins ist irgendwie komplizierter geworden. Aber es funktioniert auch:

Code: Alles auswählen

EnableExplicit

Procedure.i deleteLastLines(file.s, lines.i, blockSize.i = 4096)
	Protected fileId.i, fileSize.q, filePos.q, *p.Ascii, lastChar.i = #True
	Protected *mem = AllocateMemory(blockSize)
	
	If Not *mem
		ProcedureReturn #False
	EndIf
	
	fileId = OpenFile(#PB_Any, file)
	If Not fileId
		ProcedureReturn #False
	EndIf
	
	fileSize = Lof(fileId)
	filePos = fileSize
	Repeat
		filePos - blockSize
		If filePos < 0
			blockSize = filePos + blockSize
			filePos = 0
		EndIf
		FileSeek(fileId, filePos)
		ReadData(fileId, *mem, blockSize)
		*p = *mem + blockSize - 1
		While *p >= *mem
			If *p\a = 10 Or lastChar
				If lines = 0
					Break
				EndIf
				lines - 1
				lastChar = #False
			EndIf
			*p - 1
		Wend
		
	Until lines = 0
	
	FreeMemory(*mem)
	
	filePos + (*p - *mem + 1)
	FileSeek(fileId, filePos)
	TruncateFile(fileId)
	CloseFile(fileId)
	
	ProcedureReturn #True
EndProcedure

deleteLastLines("/home/nicolas/tmp/purebasic/zeilen.txt", 10)
Edit: Achso, es arbeitet jetzt nur mit Linefeeds. Man müsste "If *p\a = 10" durch "If *p\a = 13" ersetzen, wenn es mit Carriage Returns funktionieren soll.

Re: Zeilen txt löschen

Verfasst: 30.08.2017 23:14
von Mijikai
Nice @NicTheQuick
Ein Performancetest wäre jetzt interessant :D
Bei großen Dateien sollte deleteLastLines() schneller sein da die Chunks viel größer sind.

Re: Zeilen txt löschen

Verfasst: 31.08.2017 06:13
von Fanpost
Vielen Dank ! Damit kann ich etwas anfangen. Funktioniert Super!

Re: Zeilen txt löschen

Verfasst: 31.08.2017 09:50
von NicTheQuick
Übrigens: Wer Linux nutzt, kann es einfach so machen:

Code: Alles auswählen

nicolas@tp-w530:~/tmp/purebasic$ head -n -10 zeilen.txt > zeilen_truncated.txt
Die Datei 'zeilen.txt' wird gelesen und die die Datei 'zeilen_truncated.txt' wird erstellt und hat dann 10 Zeilen weniger als die Eingangsdatei.
In Place geht das allerdings nicht. Das könnte man vielleicht noch mit 'sed' hinbekommen, aber das wäre sicherlich wesentlich umständlicher.