所以我有一段代码可以在我可以访问的所有设备和模拟器上正常工作,除了一个。它是一款廉价的旧Android设备,华为Y330-U01,运行4.2.2。我正在使用com.google.android.gms:play-services-drive:9.8.0
进行编译。据我所知,这绝对是标准的。
我得到的文件超过了一兆字节的纯文本,我可以逐个字符地读取它,因为几千个字符(数量不一样,而不是两个或任何东西的数字之间),之前得到错误
IOException while testing the stream's first character
java.io.IOException: read failed: EBADF (Bad file number)
at libcore.io.IoBridge.read(IoBridge.java:486)
at java.io.FileInputStream.read(FileInputStream.java:179)
at libcore.io.Streams.readSingleByte(Streams.java:41)
at java.io.FileInputStream.read(FileInputStream.java:175)
at com.suchideas.android.alamode.sync.SyncActivity$b.run(Unknown Source)
Caused by: libcore.io.ErrnoException: read failed: EBADF (Bad file number)
at libcore.io.Posix.readBytes(Native Method)
at libcore.io.Posix.read(Posix.java:123)
at libcore.io.BlockGuardOs.read(BlockGuardOs.java:149)
at libcore.io.IoBridge.read(IoBridge.java:476)
at java.io.FileInputStream.read(FileInputStream.java:179)
at libcore.io.Streams.readSingleByte(Streams.java:41)
at java.io.FileInputStream.read(FileInputStream.java:175)
at com.suchideas.android.alamode.sync.SyncActivity$b.run(Unknown Source)
我非常有信心这就像耗尽RAM或磁盘空间(这个文件肯定足够空间,数百兆字节,但是设备确实想抱怨存储)并清除实际使用的东西。同样,重申一下,此代码可以完美地在同一Android版本的模拟器上运行,并且所有其他设备都经过测试。
因此。你觉得有没有解决办法?
这里是代码,您应该能够填补空白......
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
while (mGoogleApiClient.isConnecting()) {
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!mGoogleApiClient.isConnected())
return;
}
appFolder = Drive.DriveApi.getAppFolder(mGoogleApiClient);
Query query = new Query.Builder()
.addFilter(Filters.eq(SearchableField.TITLE, UPLOADED_DATABASE_NAME))
.build();
DriveApi.MetadataBufferResult metadataBufferResult = appFolder.queryChildren(mGoogleApiClient, query).await();
if (!metadataBufferResult.getStatus().isSuccess()) {
metadataBufferResult.release();
return;
}
MetadataBuffer databaseFileResults = metadataBufferResult.getMetadataBuffer();
if (databaseFileResults.getCount() == 0) {
return;
}
Metadata md = databaseFileResults.get(0);
Log.d(TAG, "Database file retrieved [" + md.getFileSize() + "B]. Created " + md.getCreatedDate() + ", modified " + md.getModifiedDate() + ".");
DriveId databaseFileID = md.getDriveId();
databaseFileResults.release();
metadataBufferResult.release();
DriveFile databaseFile = databaseFileID.asDriveFile();
DriveApi.DriveContentsResult driveContentsResult = databaseFile.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, new DriveFile.DownloadProgressListener() {
@Override
public void onProgress(long downloaded, long expected) {
}
}).await();
if (!driveContentsResult.getStatus().isSuccess()) {
return;
}
DriveContents driveContents = driveContentsResult.getDriveContents();
InputStream in = driveContents.getInputStream();
try {
int c = 0;
for(int i = 0; true; i++) {
c = in.read();
if(c == -1) break;
Log.d(TAG, "Character "+i+": "+(char)c);
}
} catch (IOException e) {
Log.e(TAG, "IOException while testing the stream character", e);
return;
}
答案 0 :(得分:2)
好吧,所以人们几乎可以肯定做得比这更好(我认为你不需要逐字逐句阅读,有些缓冲可能还可以),但经过几个小时的战斗,我找到了一种避免触发的方法这个设备上的问题。
在实践中,我建议先尝试正常driveContents.getInputStream()
。然后人们可以捕捉到上面讨论的那种错误,只有在必要时才转向这种方法。
但它有效。
方法:直接从DriveContents
而不是FileDescriptor
打开InputStream
。逐渐在缓冲区中构建它(我在这里只使用StringBuilder
,因为这是概念验证)。抓住IOExceptions
,如果您已成功阅读某些数据,请重新开始,然后继续,直至到达字符串末尾。
private static String safeDriveFileToString(DriveContents driveContents) throws IOException {
StringBuilder sb = new StringBuilder();
InputStream in;
int n = 0, nPrevious = 0;
while(true) {
in = new FileInputStream(driveContents.getParcelFileDescriptor().getFileDescriptor());
try {
int toSkip = n;
while(toSkip > 0) {
toSkip -= in.skip(toSkip);
}
int c;
while ((c = in.read()) != -1) {
sb.append((char) c);
n++;
}
if(c == -1) break;
} catch (IOException e) {
if(nPrevious == n) {
throw e;
} else {
Log.e(TAG, "Ignoring error part-way through a file:", e);
}
nPrevious = n;
}
}
return sb.toString();
}
想知道最怪异的事吗?用这种方法读完一次这个文件之后,它现在总能运作而不需要求助于此。 绝对奇怪。