mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-30 07:28:26 +01:00
Better handling of IO errors when reading/writing PGN files
This commit is contained in:
parent
913cb0d9db
commit
3ff78c2cbf
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
package org.petero.droidfish.gamelogic;
|
package org.petero.droidfish.gamelogic;
|
||||||
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -28,7 +26,6 @@ import java.util.ArrayList;
|
||||||
import org.petero.droidfish.DroidFishApp;
|
import org.petero.droidfish.DroidFishApp;
|
||||||
import org.petero.droidfish.activities.PGNFile;
|
import org.petero.droidfish.activities.PGNFile;
|
||||||
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
||||||
import org.petero.droidfish.activities.PGNFile.GameInfoResult;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@ -47,9 +44,7 @@ public class PGNFileTest extends TestCase {
|
||||||
};
|
};
|
||||||
writeFile(f, lines);
|
writeFile(f, lines);
|
||||||
PGNFile pgnFile = new PGNFile(f.getAbsolutePath());
|
PGNFile pgnFile = new PGNFile(f.getAbsolutePath());
|
||||||
Pair<GameInfoResult,ArrayList<GameInfo>> res = pgnFile.getGameInfo(null, null);
|
ArrayList<GameInfo> gi = pgnFile.getGameInfo(null, null);
|
||||||
assertEquals(GameInfoResult.OK, res.first);
|
|
||||||
ArrayList<GameInfo> gi = res.second;
|
|
||||||
assertEquals(1, gi.size());
|
assertEquals(1, gi.size());
|
||||||
assertEquals(0, gi.get(0).startPos);
|
assertEquals(0, gi.get(0).startPos);
|
||||||
assertEquals(14, gi.get(0).endPos);
|
assertEquals(14, gi.get(0).endPos);
|
||||||
|
@ -97,9 +92,7 @@ public class PGNFileTest extends TestCase {
|
||||||
};
|
};
|
||||||
writeFile(f, lines);
|
writeFile(f, lines);
|
||||||
PGNFile pgnFile = new PGNFile(f.getAbsolutePath());
|
PGNFile pgnFile = new PGNFile(f.getAbsolutePath());
|
||||||
Pair<GameInfoResult,ArrayList<GameInfo>> res = pgnFile.getGameInfo(null, null);
|
ArrayList<GameInfo> gi = pgnFile.getGameInfo(null, null);
|
||||||
assertEquals(GameInfoResult.OK, res.first);
|
|
||||||
ArrayList<GameInfo> gi = res.second;
|
|
||||||
assertEquals(2, gi.size());
|
assertEquals(2, gi.size());
|
||||||
assertEquals(0, gi.get(0).startPos);
|
assertEquals(0, gi.get(0).startPos);
|
||||||
assertEquals(660, gi.get(0).endPos);
|
assertEquals(660, gi.get(0).endPos);
|
||||||
|
@ -127,9 +120,7 @@ public class PGNFileTest extends TestCase {
|
||||||
};
|
};
|
||||||
writeFile(f, lines);
|
writeFile(f, lines);
|
||||||
PGNFile pgnFile = new PGNFile(f.getAbsolutePath());
|
PGNFile pgnFile = new PGNFile(f.getAbsolutePath());
|
||||||
Pair<GameInfoResult,ArrayList<GameInfo>> res = pgnFile.getGameInfo(null, null);
|
ArrayList<GameInfo> gi = pgnFile.getGameInfo(null, null);
|
||||||
assertEquals(GameInfoResult.OK, res.first);
|
|
||||||
ArrayList<GameInfo> gi = res.second;
|
|
||||||
assertEquals(2, gi.size());
|
assertEquals(2, gi.size());
|
||||||
assertEquals(4, gi.get(0).startPos);
|
assertEquals(4, gi.get(0).startPos);
|
||||||
assertEquals(80, gi.get(0).endPos);
|
assertEquals(80, gi.get(0).endPos);
|
||||||
|
@ -138,9 +129,8 @@ public class PGNFileTest extends TestCase {
|
||||||
assertEquals(137, gi.get(1).endPos);
|
assertEquals(137, gi.get(1).endPos);
|
||||||
assertEquals("2. w - b 1-0", gi.get(1).info);
|
assertEquals("2. w - b 1-0", gi.get(1).info);
|
||||||
|
|
||||||
res = pgnFile.getGameInfo(1);
|
gi = pgnFile.getGameInfo(1);
|
||||||
assertEquals(GameInfoResult.OK, res.first);
|
assertEquals(1, gi.size());
|
||||||
assertEquals(1, res.second.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ import org.petero.droidfish.activities.LoadFEN;
|
||||||
import org.petero.droidfish.activities.LoadScid;
|
import org.petero.droidfish.activities.LoadScid;
|
||||||
import org.petero.droidfish.activities.PGNFile;
|
import org.petero.droidfish.activities.PGNFile;
|
||||||
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
||||||
import org.petero.droidfish.activities.PGNFile.GameInfoResult;
|
|
||||||
import org.petero.droidfish.activities.Preferences;
|
import org.petero.droidfish.activities.Preferences;
|
||||||
import org.petero.droidfish.book.BookOptions;
|
import org.petero.droidfish.book.BookOptions;
|
||||||
import org.petero.droidfish.engine.EngineUtil;
|
import org.petero.droidfish.engine.EngineUtil;
|
||||||
|
@ -798,8 +797,13 @@ public class DroidFish extends Activity
|
||||||
}
|
}
|
||||||
PGNFile pgnFile = new PGNFile(fn);
|
PGNFile pgnFile = new PGNFile(fn);
|
||||||
long fileLen = FileUtil.getFileLength(fn);
|
long fileLen = FileUtil.getFileLength(fn);
|
||||||
Pair<GameInfoResult,ArrayList<GameInfo>> gi = pgnFile.getGameInfo(2);
|
boolean moreThanOneGame = false;
|
||||||
if ((fileLen > 1024 * 1024) || (gi.first == GameInfoResult.OK && gi.second.size() > 1)) {
|
try {
|
||||||
|
ArrayList<GameInfo> gi = pgnFile.getGameInfo(2);
|
||||||
|
moreThanOneGame = gi.size() > 1;
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
}
|
||||||
|
if (fileLen > 1024 * 1024 || moreThanOneGame) {
|
||||||
filename = fn;
|
filename = fn;
|
||||||
} else {
|
} else {
|
||||||
try (FileInputStream in = new FileInputStream(fn)) {
|
try (FileInputStream in = new FileInputStream(fn)) {
|
||||||
|
@ -2288,8 +2292,8 @@ public class DroidFish extends Activity
|
||||||
fenPgn.append(clip.getItemAt(i).coerceToText(getApplicationContext()));
|
fenPgn.append(clip.getItemAt(i).coerceToText(getApplicationContext()));
|
||||||
try {
|
try {
|
||||||
String fenPgnData = fenPgn.toString();
|
String fenPgnData = fenPgn.toString();
|
||||||
Pair<GameInfoResult,ArrayList<GameInfo>> gi = PGNFile.getGameInfo(fenPgnData, 2);
|
ArrayList<GameInfo> gi = PGNFile.getGameInfo(fenPgnData, 2);
|
||||||
if (gi.first == GameInfoResult.OK && gi.second.size() > 1) {
|
if (gi.size() > 1) {
|
||||||
String sep = File.separator;
|
String sep = File.separator;
|
||||||
String fn = Environment.getExternalStorageDirectory() + sep +
|
String fn = Environment.getExternalStorageDirectory() + sep +
|
||||||
pgnDir + sep + ".sharedfile.pgn";
|
pgnDir + sep + ".sharedfile.pgn";
|
||||||
|
|
|
@ -50,10 +50,11 @@ import org.petero.droidfish.ObjectCache;
|
||||||
import org.petero.droidfish.R;
|
import org.petero.droidfish.R;
|
||||||
import org.petero.droidfish.Util;
|
import org.petero.droidfish.Util;
|
||||||
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
import org.petero.droidfish.activities.PGNFile.GameInfo;
|
||||||
import org.petero.droidfish.activities.PGNFile.GameInfoResult;
|
|
||||||
import org.petero.droidfish.databinding.SelectGameBinding;
|
import org.petero.droidfish.databinding.SelectGameBinding;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -180,7 +181,7 @@ public abstract class EditPGN extends AppCompatActivity {
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
setResult(RESULT_CANCELED);
|
setResult(RESULT_CANCELED);
|
||||||
finish();
|
finish();
|
||||||
} else if (gamesInFile.size() == 0) {
|
} else if (gamesInFile.isEmpty()) {
|
||||||
pgnFile.appendPGN(pgnToSave);
|
pgnFile.appendPGN(pgnToSave);
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
|
@ -431,29 +432,33 @@ public abstract class EditPGN extends AppCompatActivity {
|
||||||
long modTime = new File(fileName).lastModified();
|
long modTime = new File(fileName).lastModified();
|
||||||
if (cacheValid && (modTime == lastModTime) && fileName.equals(lastFileName))
|
if (cacheValid && (modTime == lastModTime) && fileName.equals(lastFileName))
|
||||||
return true;
|
return true;
|
||||||
Pair<GameInfoResult, ArrayList<GameInfo>> p = pgnFile.getGameInfo(this, progress);
|
try {
|
||||||
if (p.first != GameInfoResult.OK) {
|
gamesInFile = pgnFile.getGameInfo(this, progress);
|
||||||
gamesInFile = new ArrayList<>();
|
cacheValid = true;
|
||||||
switch (p.first) {
|
lastModTime = modTime;
|
||||||
case OUT_OF_MEMORY:
|
lastFileName = fileName;
|
||||||
runOnUiThread(() -> DroidFishApp.toast(R.string.file_too_large, Toast.LENGTH_SHORT));
|
return true;
|
||||||
break;
|
} catch (PGNFile.CancelException ignore) {
|
||||||
case NOT_PGN:
|
} catch (PGNFile.NotPgnFile ex) {
|
||||||
runOnUiThread(() -> DroidFishApp.toast(R.string.not_a_pgn_file, Toast.LENGTH_SHORT));
|
runOnUiThread(() -> DroidFishApp.toast(R.string.not_a_pgn_file,
|
||||||
break;
|
Toast.LENGTH_SHORT));
|
||||||
case CANCEL:
|
} catch (FileNotFoundException ex) {
|
||||||
case OK:
|
if (!loadGame) {
|
||||||
break;
|
gamesInFile = new ArrayList<>();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
setResult(RESULT_CANCELED);
|
runOnUiThread(() -> DroidFishApp.toast(ex.getMessage(),
|
||||||
finish();
|
Toast.LENGTH_LONG));
|
||||||
return false;
|
} catch (IOException ex) {
|
||||||
|
runOnUiThread(() -> DroidFishApp.toast(ex.getMessage(),
|
||||||
|
Toast.LENGTH_LONG));
|
||||||
|
} catch (OutOfMemoryError ex) {
|
||||||
|
runOnUiThread(() -> DroidFishApp.toast(R.string.file_too_large,
|
||||||
|
Toast.LENGTH_SHORT));
|
||||||
}
|
}
|
||||||
gamesInFile = p.second;
|
setResult(RESULT_CANCELED);
|
||||||
cacheValid = true;
|
finish();
|
||||||
lastModTime = modTime;
|
return false;
|
||||||
lastFileName = fileName;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendBackResult(GameInfo gi) {
|
private void sendBackResult(GameInfo gi) {
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.petero.droidfish.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.util.Pair;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class PGNFile {
|
public class PGNFile {
|
||||||
|
@ -111,13 +110,6 @@ public class PGNFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum GameInfoResult {
|
|
||||||
OK,
|
|
||||||
CANCEL,
|
|
||||||
NOT_PGN,
|
|
||||||
OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class BytesToString {
|
private static class BytesToString {
|
||||||
private byte[] buf = new byte[256];
|
private byte[] buf = new byte[256];
|
||||||
private int len = 0;
|
private int len = 0;
|
||||||
|
@ -185,9 +177,21 @@ public class PGNFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class NotPgnFile extends IOException {
|
||||||
|
NotPgnFile() {
|
||||||
|
super("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CancelException extends IOException {
|
||||||
|
CancelException() {
|
||||||
|
super("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Return info about all PGN games in a file. */
|
/** Return info about all PGN games in a file. */
|
||||||
public Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfo(Activity activity,
|
public ArrayList<GameInfo> getGameInfo(Activity activity,
|
||||||
ProgressDialog progress) {
|
ProgressDialog progress) throws IOException {
|
||||||
if (activity == null || progress == null)
|
if (activity == null || progress == null)
|
||||||
return getGameInfoFromFile(null, -1);
|
return getGameInfoFromFile(null, -1);
|
||||||
ProgressHandler handler = new ProgressHandler(fileName, activity, progress);
|
ProgressHandler handler = new ProgressHandler(fileName, activity, progress);
|
||||||
|
@ -195,41 +199,36 @@ public class PGNFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return info about up to "maxGames" PGN games in a file. */
|
/** Return info about up to "maxGames" PGN games in a file. */
|
||||||
public Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfo(int maxGames) {
|
public ArrayList<GameInfo> getGameInfo(int maxGames) throws IOException {
|
||||||
return getGameInfoFromFile(null, maxGames);
|
return getGameInfoFromFile(null, maxGames);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfo(String pgnData,
|
public static ArrayList<GameInfo> getGameInfo(String pgnData, int maxGames) {
|
||||||
int maxGames) {
|
|
||||||
try (InputStream is = new ByteArrayInputStream(pgnData.getBytes("UTF-8"))) {
|
try (InputStream is = new ByteArrayInputStream(pgnData.getBytes("UTF-8"))) {
|
||||||
return getGameInfo(is, null, maxGames);
|
return getGameInfo(is, null, maxGames);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
return new Pair<>(GameInfoResult.NOT_PGN, null);
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfoFromFile(ProgressHandler progress,
|
private ArrayList<GameInfo> getGameInfoFromFile(ProgressHandler progress,
|
||||||
int maxGames) {
|
int maxGames) throws IOException {
|
||||||
try (InputStream is = new FileInputStream(fileName)) {
|
try (InputStream is = new FileInputStream(fileName)) {
|
||||||
return getGameInfo(is, progress, maxGames);
|
return getGameInfo(is, progress, maxGames);
|
||||||
} catch (IOException ex) {
|
|
||||||
return new Pair<>(GameInfoResult.NOT_PGN, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Return info about PGN games in a file. */
|
/** Return info about PGN games in a file. */
|
||||||
private static Pair<GameInfoResult,ArrayList<GameInfo>> getGameInfo(InputStream is,
|
private static ArrayList<GameInfo> getGameInfo(InputStream is, ProgressHandler progress,
|
||||||
ProgressHandler progress,
|
int maxGames) throws IOException {
|
||||||
int maxGames) {
|
|
||||||
ArrayList<GameInfo> gamesInFile = new ArrayList<>();
|
ArrayList<GameInfo> gamesInFile = new ArrayList<>();
|
||||||
|
long nRead = 0;
|
||||||
try (BufferedInput f = new BufferedInput(is)) {
|
try (BufferedInput f = new BufferedInput(is)) {
|
||||||
GameInfo gi = null;
|
GameInfo gi = null;
|
||||||
HeaderInfo hi = null;
|
HeaderInfo hi = null;
|
||||||
boolean inHeader = false;
|
boolean inHeader = false;
|
||||||
boolean inHeaderSection = false;
|
boolean inHeaderSection = false;
|
||||||
long filePos = 0;
|
long filePos = 0;
|
||||||
long nRead = 0;
|
|
||||||
int gameNo = 1;
|
int gameNo = 1;
|
||||||
|
|
||||||
final int INITIAL = 0;
|
final int INITIAL = 0;
|
||||||
|
@ -383,7 +382,7 @@ public class PGNFile {
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.reportProgress(filePos);
|
progress.reportProgress(filePos);
|
||||||
if (Thread.currentThread().isInterrupted())
|
if (Thread.currentThread().isInterrupted())
|
||||||
return new Pair<>(GameInfoResult.CANCEL, null);
|
throw new CancelException();
|
||||||
}
|
}
|
||||||
gi = new GameInfo();
|
gi = new GameInfo();
|
||||||
gi.startPos = filePos;
|
gi.startPos = filePos;
|
||||||
|
@ -397,14 +396,11 @@ public class PGNFile {
|
||||||
gi.info = hi.toString();
|
gi.info = hi.toString();
|
||||||
gamesInFile.add(gi);
|
gamesInFile.add(gi);
|
||||||
}
|
}
|
||||||
} catch (IOException ignore) {
|
|
||||||
} catch (OutOfMemoryError e) {
|
|
||||||
return new Pair<>(GameInfoResult.OUT_OF_MEMORY, null);
|
|
||||||
}
|
}
|
||||||
if (gamesInFile.isEmpty())
|
if (gamesInFile.isEmpty() && nRead > 1)
|
||||||
return new Pair<>(GameInfoResult.NOT_PGN, null);
|
throw new NotPgnFile();
|
||||||
|
|
||||||
return new Pair<>(GameInfoResult.OK, gamesInFile);
|
return gamesInFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mkDirs() {
|
private void mkDirs() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user