Java BufferedWriter Erstellen von Null-Zeichen

8

Ich habe Java's BufferedWriter benutzt, um in eine Datei zu schreiben, um einige Eingaben zu analysieren. Wenn ich die Datei danach öffne, scheint es jedoch Nullzeichen hinzuzufügen. Ich habe versucht, die Codierung als "US-ASCII" und "UTF8" zu spezifizieren, aber ich bekomme das gleiche Ergebnis. Hier ist mein Code-Snippet:

%Vor%

Vielleicht ist das Problem nicht einmal beim BufferedWriter?

Ich habe es auf diesen Codeblock beschränkt, denn wenn ich es auszeichne, gibt es in der Ausgabedatei keine Nullzeichen. Wenn ich eine Regex-Ersetzung in VIM durchführe, ist die Datei nullzeichenfrei (:% s /.*^ L // g).

Lassen Sie es mich wissen, wenn Sie weitere Informationen benötigen.

Danke!

BEARBEITEN: hexdump einer normalen Zeile sieht folgendermaßen aus: 0000000 5349 2a41 3030 202a

Aber wenn dieser Code ausgeführt wird, sieht der Hexdump folgendermaßen aus: 0000000 5330 2a49 4130 202a

Ich bin nicht sicher, warum die Dinge durcheinander geraten.

BEARBEITEN: Auch wenn die Datei nicht mit der Regex übereinstimmt und diesen Code durchläuft, wird sie mit Nullzeichen angezeigt.

BEARBEITEN: Hier ist ein Hexdump der ersten paar Zeilen eines Diffs: Ссылка

Befehl war: diff -y testfile.hexdump expectedoutput.hexdump

Der Rest der Zeilen ist anders als die letzten beiden.

    
SortingHat 19.03.2014, 13:48
quelle

4 Antworten

9

EDIT: Betrachtet man das von Ihnen angegebene hedddump-diff, so besteht der einzige Unterschied darin, dass einer die LF-Zeilenenden (0A) und der andere CRLF-Zeilenende (0D 0A) hat. Alle anderen Daten in Ihrem diff werden verschoben, um das zusätzliche Byte aufzunehmen.

Die CRLF ist die Standardzeile, die auf dem von Ihnen verwendeten Betriebssystem endet. Wenn Sie möchten, dass eine bestimmte Zeile in Ihrer Ausgabe endet, schreiben Sie die Zeichenfolge "\n" oder "\r\n" .

Bisher habe ich festgestellt, dass Scanner keinen Zeichensatz angibt. Es sollte das geeignete geben, von dem bekannt ist, dass die Eingabe codiert ist. Dies ist jedoch nicht die Quelle der unerwarteten Ausgabe.

    
Stuart Caie 24.03.2014, 15:07
quelle
0

Scanner.nextLine () isst die vorhandenen Zeilenenden.
Das javadoc für nextLine lautet:

  

Diese Methode gibt den Rest der aktuellen Zeile zurück und schließt am Ende keine Zeilentrennzeichen aus.

Das javadoc für BufferedWriter.newLine erklärt:

  

Schreibt ein Zeilentrennzeichen. Die Zeilentrennzeichenfolge wird durch die Systemeigenschaft line.separator definiert und muss nicht unbedingt ein einzelnes Zeilenvorschubzeichen ('\ n') sein.

In Ihrem Fall ist der Standard-Zeilentrenner Ihres Systems "\ n". Die zu analysierende EDI-Datei verwendet "\ r \ n".

Die Verwendung des systemdefinierten newLine-Separators ist in diesem Fall nicht sinnvoll. Das zu verwendende Zeilentrennzeichen wird vom Dateiformat bestimmt und sollte irgendwo in eine formatspezifische statische Konstante geschrieben werden.

Ändern Sie "out.newLine ();" "out.write (" \ r \ n ");"

    
Ryan 24.03.2014 18:57
quelle
0

Ich denke, was passiert ist das folgende

Alle Zeilen, die ^ L (ff) enthalten, werden modifiziert, um alles vor dem ^ L zu entfernen, aber zusätzlich haben Sie den Nebeneffekt in 1, dass alle \ r (cr) ebenfalls entfernt werden. Wenn cr jedoch vor ^ L erscheint, behandelt nextLine () das auch als Zeile. Beachten Sie, wie in der folgenden Ausgabedatei die Zahl von cr + nl in der Eingabedatei 6 ist und die Anzahl von cr + nl ebenfalls 6 ist, aber sie sind alle n1, so dass die Zeile mit c erhalten bleibt, weil sie behandelt wird eine andere Linie als ^ L. Wahrscheinlich nicht was du willst. Siehe unten.

Einige Beobachtungen

  1. Die Quelldatei wird auf einem System generiert, das \ r \ n verwendet, um eine neue Zeile zu definieren, und Ihr Programm wird auf einem System ausgeführt, das dies nicht tut. Aus diesem Grund werden alle Vorkommen von 0xd entfernt. Dadurch werden die beiden Dateien unterschiedlich groß, auch wenn kein ^ L vorhanden ist.

  2. Aber Sie haben wahrscheinlich # 1 übersehen, weil vim je nach dem, was beim Öffnen der Datei gelesen wird, im DOS-Modus (erkennt \ r \ n als Zeilentrennzeichen) oder im Nicht-DOS-Modus (nur \ n) arbeitet und verbirgt die Tatsache vor dem Benutzer, wenn es möglich ist. Um zu testen, musste ich mit \ v ^ m rohe Gewalt anwenden, weil ich unter Linux mit vim mehr hier .

  3. Ihr Testmittel benutzt wahrscheinlich od -x (für hex rechts)? Aber das gibt Ints aus, was nicht das ist, was Sie wollen. Berücksichtigen Sie die folgende Eingabedatei und Ausgabedatei. Nachdem Ihr Programm ausgeführt wurde. Wie in vi gesehen

Eingabedatei

%Vor%

Ausgabedatei

%Vor%

Nun, vielleicht ist das richtig, mal sehen, was od zu sagen hat

od -x der Eingabedatei

%Vor%

od -x der Ausgabedatei

%Vor%

Huh, woher kam diese Null? Aber warte von der Manpage von od

%Vor%

Oh, ok, verwenden Sie stattdessen die Option -a

od -a der Eingabe

%Vor%

od -a der Ausgabe

%Vor%

Erzwingen, dass Java ignoriert \ r

Und schließlich, all das, was gesagt wird, müssen Sie wirklich das implizite Verständnis von Java überwinden, das eine Linie, sogar im Gegensatz zur Dokumentation, abgrenzt. Selbst wenn Sie den Scanner explizit so einstellen, dass er ein Ignoriermuster verwendet, funktioniert er immer noch im Gegensatz zur Dokumentation, und Sie müssen dies durch Setzen des Trennzeichens (siehe unten) erneut aufheben. Ich habe festgestellt, das folgende wird wahrscheinlich tun, was Sie wollen, indem Sie auf Unix-Zeilensemantik bestehen. Ich fügte auch etwas Logik hinzu, um keine Leerzeile auszugeben.

%Vor%

Mit dieser Änderung ändert sich der obige Ausgang zu.

od -a der Eingabe

%Vor%

od -a der Ausgabe

%Vor%     
waTeim 24.03.2014 19:41
quelle
0

Stuart Caie lieferte die Antwort. wenn Sie nach einem Code suchen, um diese Zeichen zu vermeiden.

Grundlegendes Problem ist, Org-Datei mit anderen Zeilentrennzeichen und die neue Datei mit anderen Zeilentrennzeichen.

Ein einfacher Weg, finden Sie die Org-Datei Trennzeichen und verwenden Sie das gleiche in einer neuen Datei.

%Vor%

Hinweis ** MatchResult matchResult = fileScanner.match(); würde das matchResult für das letzte ausgeführte Match bereitstellen. Und in unserem Fall haben wir hasNextLine () verwendet - Scanner verwendet linePattern, um die nächste Zeile zu finden .. Scanner.hasNextLine Quellcode zum Auffinden der Trennlinie,

aber leider keine Möglichkeit, den Zeilentrenner zurück zu bekommen. Also habe ich den Code verwendet, um den Zeilen-Sep nur einmal zu bekommen. und nutzte diese ZeileSep für das Erstellen einer neuen Datei.

Auch nach Ihrem Code hätten Sie am Ende der Datei ein zusätzliches Zeilentrennzeichen. Korrigiert hier.

Lassen Sie mich wissen, ob das funktioniert.

    
Mani 26.03.2014 17:23
quelle