我有一个包含 234 行 string1@string2@string3 的文本文件。
kya@きゃ@キャ
kyu@きゅ@キュ
kyo@きょ@キョ
sha@しゃ@シャ
shu@しゅ@シュ
...so 234 lines
我正在编写转换器,将带有 string2 或 string3 的单词转换为带有 string1 的单词。
InputStream is = context.getResources().openRawResource(R.raw.kanatoromaji);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
try {
while ((line = reader.readLine()) != null) {
String[] parts = line.split("@");
String romaji = parts[0];
String hiragana=parts[1];
String katakana = parts[2];
if (hiragana!=null&&word.contains(hiragana)) {
word = word.replace(hiragana, romaji);//in this line getting outOfMemory error
}
if (word.contains(katakana)) {
word = word.replace(katakana, romaji);
}
}
} catch (IOException e) {
e.printStackTrace();
}
我多次调用此方法(一次运行 200k-300k 次)。所以这导致了这个错误: 07-24 00:52:32.859 10848-10848/net.joerichard.test E/AndroidRuntime:致命
EXCEPTION: main
java.lang.OutOfMemoryError
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:132)
at java.lang.StringBuilder.append(StringBuilder.java:124)
at java.lang.String.replace(String.java:1367)
at net.joerichard.test.Converter.kanaToRomaji(Converter.java:32)
at net.joerichard.test.MainActivity.migrateKanaKanji(MainActivity.java:222)
at net.joerichard.test.MainActivity.access$700(MainActivity.java:29)
at net.joerichard.test.MainActivity$10.onClick(MainActivity.java:131)
at android.view.View.performClick(View.java:4240)
at android.view.View$PerformClick.run(View.java:17721)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
我的代码有什么问题?如何解决?
更新:
根据JFPicard的回答,我将我的String word转换为StringBuilder sbWord。然后我尝试使用 StringBuilder 替换 string2 和 string3。我以前从未更换过 StringBuilder。我在 Google 中搜索并找到了这个 solution替换我的 StringBuilder 部件。现在我的代码如下所示:
public static String kanaToRomaji(Context context, String word) {
String kana = word;
StringBuilder sbWord = new StringBuilder(word);
InputStream is = context.getResources().openRawResource(R.raw.kanatoromaji);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
try {
while ((line = reader.readLine()) != null) {
String[] parts = line.split("@");
String romaji = parts[0];
String hiragana=parts[1];
String katakana = parts[2];
if (hiragana!=null&&word.contains(hiragana)) {
sbWord = replaceAll(sbWord, hiragana, romaji);//in this line getting outOfMemory error
}
if (word.contains(katakana)) {
sbWord = replaceAll(sbWord, katakana, romaji);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
char[] chars = kana.toCharArray();
for (char character: chars)
{
if(sbWord.toString().contains(String.valueOf(character)))
{
new MyLog(kana+":"+sbWord.toString());
break;
}
}
return word;
}
替换 StringBuilder 部分的方法:
public static StringBuilder replaceAll(StringBuilder builder, String from, String to)
{
int index = builder.indexOf(from);
while (index != -1)
{
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
return builder;
}
现在我收到这个错误: 07-24 01:23:52.890 13512-13512/net.joerichard.test E/AndroidRuntime:致命
EXCEPTION: main java.lang.OutOfMemoryError at java.lang.AbstractStringBuilder.move(AbstractStringBuilder.java:397) at java.lang.AbstractStringBuilder.insert0(AbstractStringBuilder.java:356) at java.lang.AbstractStringBuilder.replace0(AbstractStringBuilder.java:442) at java.lang.StringBuilder.replace(StringBuilder.java:637) at net.joerichard.test.Converter.replaceAll(Converter.java:65) at net.joerichard.test.Converter.kanaToRomaji(Converter.java:33) at net.joerichard.test.MainActivity.migrateKanaKanji(MainActivity.java:222) at net.joerichard.test.MainActivity.access$700(MainActivity.java:29) at net.joerichard.test.MainActivity$10.onClick(MainActivity.java:131) at android.view.View.performClick(View.java:4240) at android.view.View$PerformClick.run(View.java:17721) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5103) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method)
遇到这种情况怎么办?
最佳答案
我想我有一个想法。
这一行 word = word.replace(hiragana, romaji);
还有这个 word = word.replace(katakana, romaji);
每次创建一个新的字符串。 String 是不可变的,因此它会消耗内存。你的情况很多。
尝试改用 StringBuilder。
关于String.replace 上的 java.lang.OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31596991/