当我在Android Studio中启动应用程序时,必须将文件从我的资产文件夹转换为文件,才能将其读取为RDF模型。问题是我的文件现在越来越大,应用程序通常崩溃,或者文件下载时间太长。该文件约为170.384 MB,因此它是一个很大的文件,但是我希望在完成之前,该文件可以增长到约1GB。我已经在这里搜索了有关如何使文件更快下载的答案,但是我还没有看到我没有尝试过的新东西。例如,我启动了AsyncTask以便在与主UI线程不同的线程上执行“下载”操作。这阻止了我的应用程序崩溃,但是文件下载时间仍然太长,并且通常会超时。这是我在AsyncTask中下载文件的代码示例:
@Override
public Model doInBackground(String... params){
Model tdb = null;
try {
String filePath = context.getFilesDir() + File.separator + "my_turtle.ttl";
File destinationFile = new File(filePath);
FileOutputStream outputStream = new FileOutputStream(destinationFile);
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("sample_3.ttl");
byte[] buffer = new byte[1024];
int length = 0;
int per = 0;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
publishProgress(per);
per++;
}
inputStream.close();
outputStream.close();
Dataset dataset = TDBFactory.createDataset();
tdb = dataset.getNamedModel("my_dataset.ttl");
///Model m = FileManager.get().loadModel(FileManager.get().readWholeFileAsUTF8(inputStream));
TDBLoader.loadModel(tdb, filePath, false);
model = tdb;
MainActivity.presenter.setModel(model);
}catch(java.io.FileNotFoundException e){
e.printStackTrace(System.out);
}
catch(java.io.IOException e){
e.printStackTrace(System.out);
}
return tdb;
}
如您所见,我必须创建一个新的filePath和一个新文件,创建一个InputStream以便从资产中读取该文件,并将InputStream写入该文件以将RDF模型加载到TDB存储中。正是在此过程中,我的应用开始在AsyncTask中“超时”。
我遇到的另一个问题是在加载文件时更新进度栏。我不确定如何获取InputStream的长度,并且正在代码中做如下操作:
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
publishProgress(per); //Publishing progress here...
per++;
}
发布进度应触发onProgressUpdate method():
@Override
public void onProgressUpdate(Integer... progress){
progressBar.setProgress(progress[0]);
pd.setProgress(progress[0]);
}
但是由于某种原因,我的ProgressBar和ProgressDialog在整个上载时间中始终保持为0%(即使当我处理要上载的较小文件时)。我不知道为什么会这样。
下面是我的AsyncTask类的完整代码。我想发布代码的相关部分,但它们可能是在我的代码的更广泛上下文中引起问题的
public class DownloadModel extends AsyncTask<String, Integer, Model> {
Context context;
Model model = null;
ProgressDialog pd;
public DownloadModel(Context context){
this.context = context;
this.pd = new ProgressDialog(context);
}
@Override
public Model doInBackground(String... params){
Model tdb = null;
try {
String filePath = context.getFilesDir() + File.separator + "my_turtle.ttl";
File destinationFile = new File(filePath);
FileOutputStream outputStream = new FileOutputStream(destinationFile);
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("sample_3.ttl");
byte[] buffer = new byte[10000000];
int length = 0;
int per = 0;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
publishProgress(per);
per++;
}
inputStream.close();
outputStream.close();
Dataset dataset = TDBFactory.createDataset();
tdb = dataset.getNamedModel("my_dataset.ttl");
///Model m = FileManager.get().loadModel(FileManager.get().readWholeFileAsUTF8(inputStream));
TDBLoader.loadModel(tdb, filePath, false);
model = tdb;
MainActivity.presenter.setModel(model);
}catch(java.io.FileNotFoundException e){
e.printStackTrace(System.out);
}
catch(java.io.IOException e){
e.printStackTrace(System.out);
}
return tdb;
}
@Override
public void onProgressUpdate(Integer... progress){
progressBar.setProgress(progress[0]);
pd.setProgress(progress[0]);
}
@Override
public void onPreExecute(){
pd.setMessage("Loading Knowledgebase...");
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMax(100);
pd.show();
}
@Override
public void onPostExecute(Model i){
progressBar.setVisibility(View.GONE);
pd.dismiss();
}
}
谢谢您的帮助!
答案 0 :(得分:1)
如何显示进度栏
inputstream的长度与文件的大小(以字节为单位)相同。如您所知,文件大小只需乘以1024 * 1024即可将其转换为Mb字节,就可以使用此硬编码值。
在doInBackground方法内的while循环中更新,如下所示
SSL for Free
如果要处理单个文件,则无法加快该过程。
但是,如果您有多个文件,则可以使用ThreadPoolExecutor并行运行多个线程。
答案 1 :(得分:0)
我最终找到了一个非常不同的解决方案。如果有人遇到为Android Studio应用程序上传大文件的类似问题,只需考虑使用后端服务器来存储数据。这最终是我做出的决定,因为移动设备的内存有限,需要很长时间才能将大文件直接下载到应用程序中。从计算机运行服务器并在电话上连接客户端以在适当的时间检索相关信息更为有意义。否则,您最终将拥有一个占用移动设备上存储空间的文件,这将使最终用户的性能大大降低。我最终决定将RDF文件存储在计算机上,在计算机上上传文件,运行Java Server Socket,以便用户从应用程序连接客户端,然后在计算机上简单地查询文件并返回适当的文件给用户的信息。这提高了我的应用程序性能,并结束了10分钟的下载时间,这对于应用程序是不可接受的。