[英]Why can't my phone app open a file it stored in a Room Database?
Problem: My Android phone app can open various file types stored in an Android Room
pre-populated SQLite
database but it cannot open files the app itself has added to the pre-populated database (except it can open .txt files).问题:我的 Android 手机应用程序可以打开存储在
Android Room
预填充SQLite
数据库中的各种文件类型,但无法打开应用程序本身添加到预填充数据库中的文件(除非它可以打开 .txt 文件)。 I believe the issue is probably with how the I coded the copying and conversion of a selected file to byte[]
data.我相信问题可能与我如何编码所选文件的复制和转换为
byte[]
数据有关。 The app is java based, and I have done this in Java before in a desktop app, so I just can't seem to find the issue.该应用程序是基于 Java 的,我之前在桌面应用程序中使用 Java 完成了此操作,所以我似乎无法找到问题所在。 Maybe it is a permission issue, I'm just not sure and someone standing outside looking in may see what I can't.
也许这是一个许可问题,我只是不确定,站在外面的人可能会看到我看不到的东西。
What I have tried: Since the app can open various existing pre-populated files successfully from the DB, I've concentrated on and stepped through methods writing files to the DB.我尝试过的:由于该应用程序可以从数据库成功打开各种现有的预填充文件,因此我专注于并逐步介绍了将文件写入数据库的方法。 I'm not receiving any errors.
我没有收到任何错误。 I suspect it may just be minor issue since I can't seem to see it.
我怀疑这可能只是小问题,因为我似乎看不到它。
What I'm trying to do: I'm trying to emulate the desktop version of this app into a Android phone version.我正在尝试做的事情:我正在尝试将此应用程序的桌面版本模拟为 Android 手机版本。 I know it's not recommended or common practice to populate files to a DB, but this app needs to be able to read and write files to the DB supporting it.
我知道不推荐或不常用的做法是将文件填充到数据库,但此应用程序需要能够读取和写入文件到支持它的数据库。 This will be a full range of file types like the desktop version (eg, pics, docs, audio, video, etc.).
这将是各种文件类型,如桌面版本(例如,图片、文档、音频、视频等)。 However, as I stated above, .txt files seem to have no issue.
但是,正如我上面所说,.txt 文件似乎没有问题。 The user can select files stored on their phone into a table that captures the
fileName
and filePath
to a TableRow
in a TableLayout
.用户可以将存储在手机上的文件选择到一个表中,该表将
fileName
和filePath
捕获到TableLayout
的TableRow
。 Below are methods involved.下面是涉及的方法。 The plan is to refactor functionality once I get it working:
计划是在我开始工作后重构功能:
Capturing the full path and filename for each row - Uses the captured filepath to convert to a byte[]
to store the data.捕获每一行的完整路径和文件名- 使用捕获的文件路径转换为
byte[]
来存储数据。 The filename and file byte data are stored in a Files table, example, Files(fileName, fileData(byte[])).文件名和文件字节数据存储在 Files 表中,例如 Files(fileName, fileData(byte[]))。 Each file is added to an
ArrayList<Files>
which the method returns每个文件都添加到该方法返回的
ArrayList<Files>
public static List<Files> captureNoteFiles(TableLayout table){
List<Files> noteFiles = new ArrayList<>();
int i = table.getChildCount();
if(i>1){
for (int itr = 1; itr<i; itr++) { // iterating through indexes
TableRow tr = (TableRow) table.getChildAt(itr);
TextView tv = (TextView) tr.getChildAt(1); // 1 is the file path position
File f = new File(tv.getText().toString());
String n = f.getName();
try {
FileInputStream fis = new FileInputStream(f.getPath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
for (int read; (read = fis.read(buf)) != -1; ) {
bos.write(buf, 0, read);
}
fis.close();
noteFiles.add(new Files(0, n, bos.toByteArray()));
} catch (Exception e) {
e.printStackTrace();
Log.d("Input File", e.toString());
}
}
}
return noteFiles;
}
Iteration of the ArrayList - The ArrayList<Files>
is iterated and populated to the Files table and an ID capture to associate those files with a particular note of reference. ArrayList 的迭代-
ArrayList<Files>
被迭代并填充到 Files 表和 ID 捕获以将这些文件与特定的参考注释相关联。
public static void addNewNoteFiles(int noteID, List<Files> nf){
if(nf.size()>0) {
for (Files f : nf) {
long id = rdb.getFilesDao().addFile(f);
rdb.getFilesByNoteDao().insert(new FilesByNote(noteID, (int) id));
}
}
}
Files Entity文件实体
@Entity(tableName = "Files")
public class Files implements Parcelable {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "FileID")
private int fileID;
@ColumnInfo(name = "FileName")
private String fileName;
@TypeConverters(FileTypeConverter.class)
@ColumnInfo(name = "FileData", typeAffinity = ColumnInfo.TEXT)
private byte[] fileData;
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
public Files(int fileID, String fileName, byte[] fileData){
this.fileID = fileID;
this.fileName = fileName;
this.fileData = fileData;
}
}
First you are assuming that an insert works as per :-首先,您假设插入按以下方式工作:-
long id = rdb.getFilesDao().addFile(f);
rdb.getFilesByNoteDao().insert(new FilesByNote(noteID, (int) id));
What if the row isn't inserted?如果没有插入行怎么办? and returns an id of -1?
并返回-1的id?
So I'd suggest adding getters to the Files class such as :-所以我建议将 getter 添加到Files类,例如:-
public int getFileID() {
return fileID;
}
public String getFileName() {
return fileName;
}
public byte[] getFileData() {
return fileData;
}
and then add the following to FilesDao :-然后将以下内容添加到FilesDao 中:-
@Query("SELECT coalesce(length(FileData)) FROM Files WHERE FileID=:fileId")
abstract long getFilesDataLength(long fileId);
and then amending the addNewNoteFiles to be :-然后将addNewNoteFiles修改为:-
public static void addNewNoteFiles(int noteID, List<Files> nf){
final String TAG = "ADDNEWNOTE";
if(nf.size()>0) {
for (Files f : nf) {
long id = rdb.getFilesDao().addFile(f);
if (id > 0) {
long lengthOfFileData = rdb.getFilesDao().getFilesDataLength(id);
Log.d(TAG,
"Inserted File = " + f.getFileName() +
" DataLength = " + f.getFileData().length +
" ID = " + f.getFileID() +
" Length of Stored Data = " + lengthOfFileData);
if (f.getFileData().length != lengthOfFileData) {
Log.d(TAG,"WARNING FileData length MISMATCH for File = " + f.getFileName() + "\n\t Expected " + f.getFileData().length + " Found " + lengthOfFileData);
}
rdb.getFilesByNoteDao().insert(new FilesByNote(noteID, (int) id));
} else {
Log.d(TAG,"NOT INSERTED File = " + f.getFileName());
}
}
}
}
Run and check the log.运行并查看日志。 Are all the files inserted?
所有文件都插入了吗? Do the lengths match?
长度匹配吗? Are the lengths as expected (if all 0 lengths, or some, then obviously something is amiss when building the ByteArrayOutputStream)
长度是否符合预期(如果全部为 0 长度,或者一些长度,那么在构建 ByteArrayOutputStream 时显然有些问题)
You may wish to add similar for inserting the FilesByNote ie have the insert Dao return a long (it returns the rowid) and check if the value is > 0.您可能希望为插入 FilesByNote 添加类似的内容,即让插入 Dao 返回一个 long(它返回 rowid)并检查该值是否 > 0。
You wouldn't be concerned about the value if it's greater than 0, just that it is greater than 0 and thus a row was inserted.如果它大于 0,您就不会关心该值,只要它大于 0 并因此插入了一行。
The above may help to determine any issues encountered when inserting the data.以上可能有助于确定插入数据时遇到的任何问题。 If there are none found then the issue is else where.
如果没有找到,那么问题出在其他地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.