# String.format + null



## dadom110 (8. März 2010)

Hallo Zusammen,

Eine allgemeine Frage habe ich zum Thema String-Formatierung, die ich unten noch mal (wer langeweile hat) etwas konkreter gemacht habe:

*Allgemeines Problem*
Der Befehlt String.format formatiert mir das übergebene Object anhand des ebenfalls übergebenen Patterns:

```
String.format("%03d",1); // = '001'
```

Problem: "null"-werte. Kann man im Format-Pattern festlegen das er statt "null" zu schreiben Leerstrings in der angegebenen Länge ausgibt?


```
String.format("%03d",null); // = 'null'
soll aber zu: = '   '
```

Danke schon mal für alle Leser bis hier her. Warum und Wesshalb und Wieso ich das so will:

*Konkret*
Ich möchtere mehrer Dateien mit fester Satzlänge schreiben, dazu habe ich mir folgendes "Konstrukt" ausgedacht welches mir das ganze (meiner  bescheidenen Meinung nach) vereinfacht und etwas dynamischer hält ohne zu komplex zu werden.

Beschreibung:
Ich habe eine handvoll Formatierungen (über alle Nachrichten gleich) definiert die hintereinander weg bestimmte Dateiaufbauten darstellen

```
public class LineFormat {
	
	private static String NUMBER_3="%03d";
	private static String NUMBER_2="%02d";
	
	private static String CHAR_40="%1$-40s";
	private static String CHAR_8="%1$-8s";
	private static String CHAR_20="%1$-20s";
	private static String CHAR_70="%1$-70s";
	private static String CHAR_14="%1$-70s";
	private static String CHAR_1="%1$-1s";
	
	private static HashMap<String, String[]> FORMATS = new HashMap<String, String[]>() {
		{
			put("100",new String[]{NUMBER_3,CHAR_40,NUMBER_2,CHAR_14,CHAR_8,CHAR_70,CHAR_20,CHAR_40,CHAR_1});
			//....
		}
	};
```


Methode zum formatieren der übergebenen Elemente

```
public static String getFormattedString(String messageID,Object[] elements){
		String[] formatString=FORMATS.get(messageID);
		StringBuffer bufferedString=new StringBuffer();
		for (int i=0;i<formatString.length;i++){
			try{
				bufferedString.append(String.format(formatString[i], elements[i]));
				bufferedString.append(";");
			} catch (IndexOutOfBoundsException ex){
				System.out.printf("Number of elements (%d) does not match expected format-length(%d)",elements.length,formatString.length);
				return null;
			}
		}
		
		return bufferedString.toString();
	}
```

Ein kleines Beispiel


```
public static void main(String[] args) {
		Object[] elements=new Object[9];
		elements[0]=100;
		elements[1]="Eine Dok Id";
		elements[3]=00;
		elements[8]='L';
		System.out.println(LineFormat.getFormattedString("100", elements));
	}
```

Das funktioniert soweit (fast), Null-Werte werden leider als "null" beschrieben, was ich eher als Leer-String haben müsste. ("null" kann ich auch nicht durch String-Replace ersetzen, da mir dadurch ja die Feldlängen verloren gingen.

Um in dem Schema zu bleiben (es sei denn jemand kräuselt es bei meinem Design die Fußnägel) müsste ich also im String-Format-Pattern festlegen das "null" nicht geschrieben wird sondern die entsprechenden leer-zeichen.


Viele Grüße
Dom


----------



## Akeshihiro (8. März 2010)

In der Methode *getFormattedString* gibt es diese Zeile:
	
	
	



```
bufferedString.append(String.format(formatString[i], elements[i]));
```
Daraus machste einfach folgende:
	
	
	



```
bufferedString.append(String.format(formatString[i], elements[i] == null ? "" : elements[i]));
```


----------



## dadom110 (8. März 2010)

Jaja, ich glaub du guckst mir auf den Monitor  das hatte ich davor auch stehen. Leider führt die Formatierung eines Leerstrings als Zahl zu einer Exception:


```
Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.String
	at java.util.Formatter$FormatSpecifier.failConversion(Unknown Source)
	at java.util.Formatter$FormatSpecifier.printInteger(Unknown Source)
	at java.util.Formatter$FormatSpecifier.print(Unknown Source)
	at java.util.Formatter.format(Unknown Source)
	at java.util.Formatter.format(Unknown Source)
	at java.lang.String.format(Unknown Source)
	at de.dd.client.TestMain.main(TestMain.java:15)
```

Alles als String zu formatieren stößt dann schlussendlich bei einem Float Value (welchen ich mit spezifischen Vor- und Nachkommastellen formatieren muss) an seine Grenze.
Die Exception könnte ich teoretisch zwar abfangen, aber dann müsste ich (wenn das ganze weiterhin als Format-String vorgehalten werden soll) die Zahlen aus dem Format-String parsen, was ich so unelegant finde das ich es nur sehr ungerne machen würde

Grüße
Dom


----------



## mongole (17. Mai 2010)

Hi!

Habt ihr dazu schon eine Lösung gefunden? Ich steh nämlich genau dem selben Problem. Will eine Datei mit fixen Feldlängen schreiben und der Formatter will nicht so wie ich bei 'null' Werten 

Übrigens, diene Lösung find ich echt einfach und elegant! Gefällt mir 

lg,
mongole


----------



## dadom110 (19. Mai 2010)

HuHu,

Leider habe ich keine elegante Lösung gefunden (alá Attribut beim LineFormatter setzen oder dergleichen). Das einzige was mir als Workaround eingefallen ist, bei Null-Werten die formatierung onTheFly zu verändern. Wie gesagt nicht besonders schön, aber hat seinen Zweck damals erfüllt. Leider habe den SourceCode nicht vorliegen. 

Sah im allgemeinen so aus

Bei einem Null-Objekt
- wenn Format auf  "s" Endet (String), Wert durch " " ersetzen

Wenn man Zahlenwerte als 0er Reihen darstellen kann/möchte ansonsten den Wert auf "0" setzen.
Wenn man aber leerzeichen anstatt 0er-Zahlen benötigt:

- wenn Format auf "d" Endet (dezimalzahl), Wert durch " " ersetzen und FormatString auf einen String setzen (Ersetze "d" durch "s")
- wenn Format auf "f" Endet (gleitkommazahl) GANZ blöd (kam hier im Beispiel nicht vor), muss man die Zahlenwerte aus dem FormatString parsen, die Zusammenzählen und + 1 Rechnen und daraus ein neues String Format basteln :-(  (also so was wie "%5.2f", float mit 2 Nachkommastellen muss zu einem Format: "%08s" werden (5 Vorkommastellen + 2Nachkommastellen + 1Komma)

Bin aber gerne offen für andere Vorschläge 

Grüße
D


----------



## mongole (19. Mai 2010)

Im Endeffekt hab ich mir auch so was auf die Art gebastelt. Nur, dass ich mir ganz stumpf in einer for Schleife " " in einen StringBuffer gestopft hab. Nicht sehr elegant, aber egal.
Ich find's nur echt schad, weil durch dieses blöde 'null' Problem, der String Formatter so wie er ist, eigentlich unbrauchbar wird. 

Wenn man für ein Fixed Length Dateiformat einfach einen Format String baut und die Werte befüllt und den Formatter dann noch mit einem File Output Stream anlegt, könnt man ganz einfach so das File schreiben, aber durch das 'null' problem geht nix...


----------



## dadom110 (19. Mai 2010)

Naja, wie gesagt es geht ja im Grunde schon genau so., nur das die Formatierungs Methode eben noch die Prüfung auf "null" macht und die oben genannten Änderungen des Format-Patterns macht falls denn ein Null-Wert kommt. Damit bleibt man technisch bei den Formatierungen, nur elegant ist eben was anderes (gerade ein FloatFormat onTheFly in ein StringFormat um zu wandeln ist nicht ganz soo schön)


----------

