Printf ได้เพิ่มใน Java ด้วยรีลีส 1.5 แต่ฉันไม่สามารถหาวิธีส่งเอาต์พุตไปยังสตริงได้แทนที่จะเป็นไฟล์ (ซึ่งเป็นสิ่งที่ sprintf ทำใน C) ไม่มีใครรู้วิธีการทำเช่นนี้?
Printf ได้เพิ่มใน Java ด้วยรีลีส 1.5 แต่ฉันไม่สามารถหาวิธีส่งเอาต์พุตไปยังสตริงได้แทนที่จะเป็นไฟล์ (ซึ่งเป็นสิ่งที่ sprintf ทำใน C) ไม่มีใครรู้วิธีการทำเช่นนี้?
คำตอบ:
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
สตริงเป็นประเภทที่ไม่เปลี่ยนรูป คุณไม่สามารถแก้ไขได้ แต่คืนค่าอินสแตนซ์สตริงใหม่เท่านั้น
เนื่องจากการจัดรูปแบบด้วยวิธีการอินสแตนซ์ทำให้รู้สึกเล็กน้อยเพราะมันจะต้องถูกเรียกว่า:
String formatted = "%s: %s".format(key, value);
ผู้เขียน Java ดั้งเดิม (และผู้เขียน. NET) ตัดสินใจว่าวิธีการแบบคงที่เหมาะสมกว่าในสถานการณ์นี้เนื่องจากคุณไม่ได้ปรับเปลี่ยนเป้าหมาย แต่แทนที่จะเรียกวิธีการจัดรูปแบบและส่งผ่านสตริงการป้อนข้อมูลแทน
นี่คือตัวอย่างของเหตุผลที่format()
จะโง่เป็นวิธีการตัวอย่าง ใน. NET (และอาจเป็น Java) Replace()
เป็นวิธีการอินสแตนซ์
คุณสามารถทำได้:
"I Like Wine".Replace("Wine","Beer");
อย่างไรก็ตามไม่มีอะไรเกิดขึ้นเนื่องจากสตริงไม่เปลี่ยนรูป Replace()
พยายามคืนสตริงใหม่ แต่มันถูกกำหนดเป็นอะไร
นี่เป็นสาเหตุของความผิดพลาดหน้าใหม่ที่พบบ่อยเช่น:
inputText.Replace(" ", "%20");
อีกครั้งไม่มีอะไรเกิดขึ้นแทนคุณต้องทำ:
inputText = inputText.Replace(" ","%20");
ทีนี้ถ้าคุณเข้าใจว่าสายนั้นไม่เปลี่ยนรูป หากคุณไม่ทำเช่นนั้นคุณก็สับสน สถานที่ที่เหมาะสมสำหรับการReplace()
อยู่ที่ซึ่งformat()
เป็นวิธีการคงที่ของString
:
inputText = String.Replace(inputText, " ", "%20");
ตอนนี้ไม่มีคำถามว่าเกิดอะไรขึ้น
คำถามจริงคือทำไมผู้เขียนของกรอบเหล่านี้ตัดสินใจว่าควรเป็นวิธีการตัวอย่างและแบบคงที่อื่น ๆ ? ในความคิดของฉันทั้งสองแสดงออกอย่างหรูหรามากขึ้นเป็นวิธีการคงที่
โดยไม่คำนึงถึงความคิดเห็นของคุณความจริงก็คือคุณมีแนวโน้มที่จะทำผิดพลาดน้อยกว่าในการใช้เวอร์ชันคงที่และรหัสนั้นง่ายต่อการเข้าใจ (ไม่มี Gotchas ที่ซ่อนอยู่)
แน่นอนมีวิธีการบางอย่างที่สมบูรณ์แบบเป็นวิธีการเช่นใช้ String.Length ()
int length = "123".Length();
ในสถานการณ์เช่นนี้เห็นได้ชัดว่าเราไม่ได้พยายามแก้ไข "123" เราเพียงตรวจสอบและคืนความยาว นี่คือตัวเลือกที่สมบูรณ์แบบสำหรับวิธีการอินสแตนซ์
กฎง่ายๆของฉันสำหรับวิธีการอินสแตนซ์บนวัตถุที่ไม่เปลี่ยนรูป:
โซลูชันทั้งสองทำงานเพื่อจำลอง printf แต่ในวิธีที่ต่างกัน ตัวอย่างเช่นในการแปลงค่าเป็นสตริงฐานสิบหกคุณมีวิธีแก้ไขปัญหา 2 ข้อต่อไปนี้:
ด้วยformat()
, ใกล้กับsprintf()
:
final static String HexChars = "0123456789abcdef";
public static String getHexQuad(long v) {
String ret;
if(v > 0xffff) ret = getHexQuad(v >> 16); else ret = "";
ret += String.format("%c%c%c%c",
HexChars.charAt((int) ((v >> 12) & 0x0f)),
HexChars.charAt((int) ((v >> 8) & 0x0f)),
HexChars.charAt((int) ((v >> 4) & 0x0f)),
HexChars.charAt((int) ( v & 0x0f)));
return ret;
}
ด้วยreplace(char oldchar , char newchar)
ค่อนข้างเร็ว แต่ค่อนข้าง จำกัด :
...
ret += "ABCD".
replace('A', HexChars.charAt((int) ((v >> 12) & 0x0f))).
replace('B', HexChars.charAt((int) ((v >> 8) & 0x0f))).
replace('C', HexChars.charAt((int) ((v >> 4) & 0x0f))).
replace('D', HexChars.charAt((int) ( v & 0x0f)));
...
มีวิธีที่สามที่ประกอบด้วยเพียงการเพิ่มตัวอักษรret
ทีละตัว (ตัวอักษรเป็นตัวเลขที่เพิ่มซึ่งกันและกัน ) เช่นใน:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
... แต่นั่นน่าเกลียดจริงๆ
คุณสามารถทำ printf ให้กับสิ่งใดก็ตามที่เป็น OutputStream ด้วย PrintStream อย่างนี้พิมพ์ลงในกระแสสตริง:
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
baos.reset(); //need reset to write new string
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
System.out.println(baos.toString());
baos.reset();
สตรีมสตริงสามารถสร้างได้เช่น ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();