mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-27 06:10:28 +01:00
DroidFish: Fixed out of memory error when receiving large PGN files.
If receiving a large PGN file as a content stream from another app, store the data in a temporary file instead of reading it all into memory. This also makes content containing more than one game work correctly by letting the user select which game to open.
This commit is contained in:
parent
5c6b1408f4
commit
f211786b74
|
@ -21,11 +21,13 @@ package org.petero.droidfish;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -45,6 +47,9 @@ import org.petero.droidfish.activities.EditPGNLoad;
|
|||
import org.petero.droidfish.activities.EditPGNSave;
|
||||
import org.petero.droidfish.activities.LoadFEN;
|
||||
import org.petero.droidfish.activities.LoadScid;
|
||||
import org.petero.droidfish.activities.PGNFile;
|
||||
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
||||
import org.petero.droidfish.activities.PGNFile.GameInfoResult;
|
||||
import org.petero.droidfish.activities.Preferences;
|
||||
import org.petero.droidfish.book.BookOptions;
|
||||
import org.petero.droidfish.engine.EngineUtil;
|
||||
|
@ -163,7 +168,6 @@ public class DroidFish extends Activity
|
|||
// FIXME!!! Implement bookmark mechanism for positions in pgn files
|
||||
// FIXME!!! Add support for "Chess Leipzig" font
|
||||
|
||||
// FIXME!!! Computer clock should stop if phone turned off (computer stops thinking if unplugged)
|
||||
// FIXME!!! Add support for "no time control" and "hour-glass time control" as defined by the PGN standard
|
||||
|
||||
// FIXME!!! Add chess960 support
|
||||
|
@ -174,7 +178,6 @@ public class DroidFish extends Activity
|
|||
|
||||
// FIXME!!! Option to display coordinates in border outside chess board.
|
||||
|
||||
// FIXME!!! Handle PGN non-file intents with more than one game.
|
||||
// FIXME!!! Save position to fen/epd file
|
||||
|
||||
// FIXME!!! Selection dialog for going into variation
|
||||
|
@ -719,19 +722,31 @@ public class DroidFish extends Activity
|
|||
filename = Uri.decode(filename);
|
||||
}
|
||||
if ((filename == null) &&
|
||||
("content".equals(scheme) ||
|
||||
"file".equals(scheme))) {
|
||||
("content".equals(scheme) || "file".equals(scheme))) {
|
||||
ContentResolver resolver = getContentResolver();
|
||||
InputStream in = resolver.openInputStream(data);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (true) {
|
||||
byte[] buffer = new byte[16384];
|
||||
int len = in.read(buffer);
|
||||
if (len <= 0)
|
||||
break;
|
||||
sb.append(new String(buffer, 0, len));
|
||||
String sep = File.separator;
|
||||
String fn = Environment.getExternalStorageDirectory() + sep +
|
||||
pgnDir + sep + ".sharedfile.pgn";
|
||||
try {
|
||||
FileUtil.writeFile(in, fn);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
PGNFile pgnFile = new PGNFile(fn);
|
||||
long fileLen = FileUtil.getFileLength(fn);
|
||||
Pair<GameInfoResult,ArrayList<GameInfo>> gi = pgnFile.getGameInfo(this, null, 2);
|
||||
int nGames = gi.second.size();
|
||||
if ((fileLen > 1024 * 1024) || (gi.first == GameInfoResult.OK && nGames > 1)) {
|
||||
filename = fn;
|
||||
} else {
|
||||
in = new FileInputStream(fn);
|
||||
try {
|
||||
pgnOrFen = FileUtil.readFromStream(in);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
pgnOrFen = sb.toString();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -20,9 +20,12 @@ package org.petero.droidfish;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -60,4 +63,34 @@ public class FileUtil {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Read data from input stream and write to file. */
|
||||
public static void writeFile(InputStream is, String outFile) throws IOException {
|
||||
OutputStream os = new FileOutputStream(outFile);
|
||||
try {
|
||||
byte[] buffer = new byte[16384];
|
||||
while (true) {
|
||||
int len = is.read(buffer);
|
||||
if (len <= 0)
|
||||
break;
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
} finally {
|
||||
os.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the length of a file, or -1 if length can not be determined. */
|
||||
public static final long getFileLength(String filename) {
|
||||
try {
|
||||
RandomAccessFile raf = new RandomAccessFile(filename, "r");
|
||||
try {
|
||||
return raf.length();
|
||||
} finally {
|
||||
raf.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,6 +161,13 @@ public class PGNFile {
|
|||
/** Return info about all PGN games in a file. */
|
||||
public final Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfo(Activity activity,
|
||||
final ProgressDialog progress) {
|
||||
return getGameInfo(activity, progress, -1);
|
||||
}
|
||||
|
||||
/** Return info about all PGN games in a file. */
|
||||
public final Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfo(Activity activity,
|
||||
final ProgressDialog progress,
|
||||
int maxGames) {
|
||||
ArrayList<GameInfo> gamesInFile = new ArrayList<GameInfo>();
|
||||
gamesInFile.clear();
|
||||
long fileLen = 0;
|
||||
|
@ -326,6 +333,10 @@ public class PGNFile {
|
|||
gi.endPos = filePos;
|
||||
gi.info = hi.toString();
|
||||
gamesInFile.add(gi);
|
||||
if ((maxGames > 0) && gamesInFile.size() >= maxGames) {
|
||||
gi = null;
|
||||
break;
|
||||
}
|
||||
final int newPercent = (int)(filePos * 100 / fileLen);
|
||||
if (newPercent > percent) {
|
||||
percent = newPercent;
|
||||
|
|
|
@ -135,6 +135,10 @@ public class PGNFileTest extends TestCase {
|
|||
assertEquals(80, gi.get(1).startPos);
|
||||
assertEquals(137, gi.get(1).endPos);
|
||||
assertEquals("2. w - b 1-0", gi.get(1).info);
|
||||
|
||||
res = pgnFile.getGameInfo(null, null, 1);
|
||||
assertEquals(GameInfoResult.OK, res.first);
|
||||
assertEquals(1, res.second.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user