Verschwindende Sonderzeichen...

mccae

Senfdazugeber
Genau!

Verdächtiger: Debian Linux Root Server

Vorwurf: Das entführen unschuldiger Sonderzeichen und ersetzen durch Fragezeichen.

Könnt ihr mir helfen den Fall zu lösen?

Es geht um folgendes:

Wenn ich meine Client/Server Applikation auf meinen Linux server laufen lasse, so kommt am ende einer Verarbeitungskette ein verunstalteter String heraus..

Prozedur:

Client sendet String mit Sonderzeichen (z.B.: "FRUCHT = Hülsenfrüchte") an den Server über einen einfachen Socket und Object input und outputstreams.

Der String wird gelesen und auf die Platte geschrieben.

Irgendwann wird diese Datei wieder gelesen (mit der Klasse Properties) und der String irgendwann, zurückgeschickt.

Was jedoch retour kommt, ist FRUCHT = H?lsenfr?chte,

Leider passiert das mit den verschluckten Sonderzeichen nur auf meinem Linux server.
Wenn ich alles Lokal auf Windows XP teste, ist alles OK.

Kann es etwa seien, dass beim Einlesen der Datei durch die Properties Klasse etwas schief läuft?

Um die Dateien zu lesen und zu schreiben verkette ich einen FileInput/Output stream mit einem BufferedInput/Output stream.

Geschrieben wird über streamname.write(String s); und gelesen durch übergeben des InputStreams an ein Objekt der Properties Klasse und anschließendem Aufrufen von load();

Die Map mit allen Strings wird übers Internet gesendet indem ein serialisiertes Objekt einer Klasse welche diese enthält in einen ObjectOuputStream geschoben wird, der wiederum direkt mit dem OutputStream des Sockets verkettet ist.

Umgekehrt ist es genau so...

Versteht jemand was ich meine, und hat jemand eine Ahnung?
 
Gelesen und geschrieben wird im default charset. Und das ist bei Linux UTF-8 und bei Windows cp irgendwas. Ich würde dir raten daher beim lesen und schreiben das Charset mit anzugeben. Dann sollte auch eigentlich nichts schiefgehen.
 
Gelesen und geschrieben wird im default charset. Und das ist bei Linux UTF-8 und bei Windows cp irgendwas. Ich würde dir raten daher beim lesen und schreiben das Charset mit anzugeben. Dann sollte auch eigentlich nichts schiefgehen.

Huhu,

Ich hab mich bei den streams ein bisschen vertan, so wird bei mir geschrieben:

Java:
public synchronized void cfgWrite(){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(path));
				
			for(int i = 0;i<config.length;i++){
				out.write(config[i][0] + " " + config[i][1] + "\n");	
			}
				
		        out.close();

			} catch (IOException e) {
				exThrown(e);
			}
	}

Wie kann ich denn das Charset angeben?

Die Java API schweigt...
 
Die Java API sagt dazu sogar im FileWriter

Convenience class for writing character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable. To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream.

Hardcodiertes \n ist auch nicht so fein. Nutze stattdessen besser

private static final String LINE_SEPARATOR = System.getProperty("line.separator")

als Konstante in einer passenden Klasse.
 
Die Java API sagt dazu sogar im FileWriter



Hardcodiertes \n ist auch nicht so fein. Nutze stattdessen besser

private static final String LINE_SEPARATOR = System.getProperty("line.separator")

als Konstante in einer passenden Klasse.

Vielen Dank!

Das Problem wär damit erledigt,...

Ich hätt aber noch nebenbei eine Frage, wenn du schon mal da bist :)

Wie kann ich verhindern, dass ein "\n" welches so als Text in der Datei steht als Zeilenumbruch erkannt wird, und wie kann ich dieses wieder als "\n" in die Datei schreiben ohne dass ein Zeilenumbruch entsteht?

Einfach ein replace all auf den String anwenden?
Denn was mich verwirrt ist, dass ein backslash in java und dieser komischen RegEx engine ein Escapezeichen ist.

Ist s = s.replaceAll("\\\\n" , "\\\\\\\\n"); richtig?
 
Hi.
Wie kann ich verhindern, dass ein "\n" welches so als Text in der Datei steht als Zeilenumbruch erkannt wird, und wie kann ich dieses wieder als "\n" in die Datei schreiben ohne dass ein Zeilenumbruch entsteht?
Wenn in der Datei die 2 Zeichen <BACKSLASH> und <n> hintereinander drin stehen mußt du gar nichts verhindern, denn das wird ganz normal gelesen. Nur das ASCII Zeichen 0x10 wird als \n interpretiert.

Im Java Code mußt du natürlich in Stringliteralen den Backslash entwerten, da sonst der Compiler \n als ASCII 0x10 interpretiert: "\\n".

Gruß
 
Hi.
Wenn in der Datei die 2 Zeichen <BACKSLASH> und <n> hintereinander drin stehen mußt du gar nichts verhindern, denn das wird ganz normal gelesen. Nur das ASCII Zeichen 0x10 wird als \n interpretiert.

Im Java Code mußt du natürlich in Stringliteralen den Backslash entwerten, da sonst der Compiler \n als ASCII 0x10 interpretiert: "\\n".

Gruß

Huhu,

Wenn ich den Text (mit einem Backslash und n) einlese, und diesen dann als text einer JTextArea setze (setText(String s)) dann wird dennoch ein Zeilenumbruch eingefügt,

Anderes Beispiel: Ich habe ein JTextField und setze dessen Text indem ich den ausgelesenen String nehme. Statt einem \n (so wie es in der Datei steht) wird diese Zeichenkombi verschluckt (da ein JTextField logischerweise nicht multiline fähig ist).

Wenn ich dieses eingelesene \n dann wieder in die Datei schreibe wird ein Zeilenumbruch eingefügt.

Es ist also nötig irgendwas mit diesem String zu machen damit das "\n" als dieses im Text erscheint...
 
Wenn ich den Text (mit einem Backslash und n) einlese, und diesen dann als text einer JTextArea setze (setText(String s)) dann wird dennoch ein Zeilenumbruch eingefügt,

Anderes Beispiel: Ich habe ein JTextField und setze dessen Text indem ich den ausgelesenen String nehme. Statt einem \n (so wie es in der Datei steht) wird diese Zeichenkombi verschluckt (da ein JTextField logischerweise nicht multiline fähig ist).
Ist so nicht nachvollziebar.

Dateiinhalt:
Code:
hallo, welt!\ndies ist\n ein test.
Java:
// Groovy:

def file = new File("c:/test.txt")
def text = file.getText()

aTextArea.setText(text)
aTextField.setText(text)
Resultat siehe Screenshot.

Gruß
 

Anhänge

  • testbn.JPG
    testbn.JPG
    14,1 KB · Aufrufe: 48
Ist so nicht nachvollziebar.

Dateiinhalt:
Code:
hallo, welt!\ndies ist\n ein test.
Java:
// Groovy:

def file = new File("c:/test.txt")
def text = file.getText()

aTextArea.setText(text)
aTextField.setText(text)
Resultat siehe Screenshot.

Gruß

Huhu, kann ich wiederum nicht nachvollziehen.
Hier ein Beispiel welches auch zeigt was ich meine:

Es werden Properties aus einer Datei namens text.txt geladen.

Die text.txt enthält:

Code:
text = Ein einfacher Text mit mehreren Backslash n,\num zu beweisen, dass java geschriebene übernimmt und neue Lines anfängt.\nund ja, es t!\nDie TextArea übernimmt dies als neue Lines, und das Textfield verschluckt alles einfach.\nBöse Böse

Hier das ausführbare Java Programm:
Bitte zuerst die Datei namens test.txt im project directory erstellen (oder woanders, dann aber den path anpassen)

Java:
package ***.misc;

import java.awt.*;
import java.awt.event.*;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

import javax.swing.*;

/**
 * @author mccae
 */
public class BSNTest extends JFrame {
   
    /**
     *
     */
    private static final long serialVersionUID = 1L;
   
    public BSNTest() {
        initComponents();
    }
   
    public static void main(String[]args){
        BSNTest t = new BSNTest();
        t.setVisible(true);
    }
   
    private void button1ActionPerformed(ActionEvent e) {
        FileInputStream stream;
        Properties props = new Properties();
        try {
            stream = new FileInputStream("text.txt");
            props.load(stream);
            stream.close();
        }
       
        catch (FileNotFoundException e2) {
        }
       
        catch (IOException e3) {
           
        }
        textArea.setText(props.getProperty("text"));
        textField.setText(props.getProperty("text"));
    }
   
    private void button2ActionPerformed(ActionEvent e) {
        BufferedWriter out = null;
         try {
            out = new BufferedWriter(new FileWriter("text.txt"));
            out.write(textField.getText());
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        try {
            out.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

    private void initComponents() {
        scrollPane1 = new JScrollPane();
       
        textArea = new JTextArea();
        textArea.setEditable(false);
       
        textField = new JTextField();
        textField.setEditable(false);
       
        button = new JButton();
        button1 = new JButton();
        button1.setEnabled(false);

        //======== this ========
        setTitle("BSN Test :O");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        Container contentPane = getContentPane();

        //======== scrollPane1 ========
        {
            scrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            scrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
            scrollPane1.setViewportView(textArea);
        }

        //---- button ----
        button.setText("Load text.txt");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                button1ActionPerformed(e);
            }
        });
       
        //---- button ----
        button1.setText("Write text.txt");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                button2ActionPerformed(e);
            }
        });

        GroupLayout contentPaneLayout = new GroupLayout(contentPane);
        contentPane.setLayout(contentPaneLayout);
        contentPaneLayout.setHorizontalGroup(
            contentPaneLayout.createParallelGroup()
                .addGroup(contentPaneLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(contentPaneLayout.createParallelGroup()
                        .addComponent(textField, GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE)
                        .addComponent(scrollPane1, GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE)
                        .addGroup(contentPaneLayout.createSequentialGroup()
                            .addComponent(button)
                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(button1, GroupLayout.PREFERRED_SIZE, 120, GroupLayout.PREFERRED_SIZE)))
                    .addContainerGap())
        );
        contentPaneLayout.setVerticalGroup(
            contentPaneLayout.createParallelGroup()
                .addGroup(contentPaneLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(textField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                    .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                        .addComponent(button)
                        .addComponent(button1))
                    .addContainerGap(13, Short.MAX_VALUE))
        );
        pack();
        setLocationRelativeTo(getOwner());
    }

    private JScrollPane scrollPane1;
    private JTextArea textArea;
    private JTextField textField;
    private JButton button;
    private JButton button1;
}

Was soll ich jetzt tun?
 
Zuletzt bearbeitet:
Hi.

Aha, du verwendest Property Dateien. Da werden allerdings einige Zeichen beim Laden ersetzt.

Wenn du nicht möchtest, das ein \n als Zeilenterminierungszeichen umgesetzt wird, dann müßtest du einfach \\n in die Property Datei schreiben.

Wie es aussieht schreibst du die Property Dateien selbst (in der cfgWrite() Methode)? Das ist keine gute Idee. Nimm doch einfach die Properties.store() Methode.

Gruß
 
Zurück