私が解決しようとしている問題は、キャリッジリターンを含む可能性のある文字列が与えられ、各行が設定された文字数を超えないように追加のキャリッジリターンを挿入することです。また、可能であれば、単語をそのまま保持するようにします。
Java または Scala に必要な機能を備えたライブラリはありますか?
私が解決しようとしている問題は、キャリッジリターンを含む可能性のある文字列が与えられ、各行が設定された文字数を超えないように追加のキャリッジリターンを挿入することです。また、可能であれば、単語をそのまま保持するようにします。
Java または Scala に必要な機能を備えたライブラリはありますか?
java.text
パッケージには、改行を挿入できる場所を教えてくれるBreakIterator クラスがありますが、使い方が少し複雑です。このような正規表現は、仕事の 80% を行うことができます:
str += "\n"; // Needed to handle last line correctly
// insert line break after max 50 chars on a line
str = str.replaceAll("(.{1,50})\\s+", "$1\n");
Apache commons lang ライブラリには、長いテキスト行を単語境界で指定された長さの複数行に折り返すメソッドWordUtils
を含むクラスがあります。wrap
誰かが興味を持っているなら、WordUtils を指摘してくれた Joni に感謝します。
private static String wrappify(String source, int lineLength, String eolMarker){
String[] lines = source.split(eolMarker);
StringBuffer wrappedStr = new StringBuffer();
for (String line : lines) {
if(line.length() <= lineLength){
wrappedStr.append(line + eolMarker);
}else{
wrappedStr.append(WordUtils.wrap(line, lineLength, eolMarker, true) + eolMarker);
}
}
return wrappedStr.replace(wrappedStr.lastIndexOf(eolMarker), wrappedStr.length(), "").toString();
}
public static String addReturns(String s, int maxLength)
{
String newString = "";
int ind = 0;
while(ind < s.length())
{
String temp = s.substring(ind, Math.min(s.length(), ind+maxLength));
int lastSpace = temp.lastIndexOf(" ");
int firstNewline = temp.indexOf("\n");
if(firstNewline>-1)
{
newString += temp.substring(0, firstNewline + 1);
ind += firstNewline + 1;
}
else if(lastSpace>-1)
{
newString += temp.substring(0, lastSpace + 1) + "\n";
ind += lastSpace + 1;
}
else
{
newString += temp + "\n";
ind += maxLength;
}
}
return newString;
}
正規表現を使用したくない場合は、これでうまくいきます。
System.out.println(addReturns("Hi there, I'm testing to see if this\nalgorithm is going to work or not. Let's see. ThisIsAReallyLongWordThatShouldGetSplitUp", 20));
出力:
Hi there, I'm
testing to see if
this
algorithm is going
to work or not.
Let's see.
ThisIsAReallyLongWor
dThatShouldGetSplitU
p
といったことから始めてもいいと思います。単語が MAX_LINE_LENGTH を超える場合は、特別なケースを処理する必要があることに注意してください。
package com.ekse.nothing;
public class LimitColumnSize {
private static String DATAS = "It was 1998 and the dot-com boom was in full effect. I was making websites as a 22 year old freelance programmer in NYC. I charged my first client $1,400. My second client paid $5,400. The next paid $24,000. I remember the exact amounts — they were the largest checks I’d seen up til that point.\n"
+ "Then I wrote a proposal for $340,000 to help an online grocery store with their website. I had 5 full time engineers at that point (all working from my apartment) but it was still a ton of dough. The client approved, but wanted me to sign a contract — everything had been handshakes up til then.\n"
+ "No prob. Sent the contract to my lawyer. She marked it up, sent it to the client. Then the client marked it up and sent it back to my lawyer. And so on, back and forth for almost a month. I was inexperienced and believed that this is just how business was done."
+ "Annoyed by my lawyering, the client eventually gave up and hired someone else.";
private static int MAX_LINE_LENGTH = 80;
private static char[] BREAKING_CHAR = {' ', ',', ';', '!', '?', ')', ']', '}'}; // Probably some others
public static void main(String[] args) {
String current = DATAS;
String result = "";
while (current.length() != 0) {
for (int i = (current.length() - 1) < MAX_LINE_LENGTH ? current.length() - 1 : MAX_LINE_LENGTH; i >= 0; i--) {
if (current.charAt(i) == '\n') {
result += current.substring(0, i);
current = current.substring(i + 1);
break;
} else if (isBreakingChar(current.charAt(i))) {
result += current.substring(0, i) + "\n";
current = current.substring(i + 1);
break;
} else if (i == 0 && (current.length() - 1) < MAX_LINE_LENGTH) {
result += current;
current = "";
} else {
// Line cannot be break, try to go to the right and find the next BREAKING_CHAR
}
}
}
System.out.println(result);
}
private static boolean isBreakingChar(char c) {
for (int i = 0; i < BREAKING_CHAR.length; ++i) {
if (c == BREAKING_CHAR[i]) {
return true;
}
}
return false;
}
}