我写这篇文章是因为我受够了......
我再也受不了了……
我阅读并阅读并阅读......然后,再阅读一点......就像我在这里写这个问题之前一样!
我正在尝试将现成的 sqlite 数据库从资产复制到应用程序数据库文件夹。
我已经尝试了复制代码、路径代码等的所有组合。
这是来自SO:
/**
* http://stackoverflow.com/questions/10738623/copy-database-from-assets-folder-in-unrooted-device
* Copies your database from your local assets-folder to the just created
* empty database in the system folder, from where it can be accessed and
* handled. This is done by transfering bytestream.
* */
public static void copyDataBase(String dbname, Context mContxt) throws IOException {
myContext = mContxt;
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(dbname);
// Path to the just created empty db
// String outFileName = "/data/data/" + MainActivity.PACKAGE_NAME + "/databases/" + dbname;
String outFileName1 = "/data/data/" + MainActivity.PACKAGE_NAME; // + "/databases/" + dbname;
String outFileName = myContext.getFilesDir().getAbsolutePath().replace("files", "databases/"); // + "/Database/";
File newDir = null;
File dir = new File(myContext.getApplicationInfo().dataDir+"/databases");
dir.mkdirs();
if (!dir.isDirectory()) {
Log.v(TAG, "NOTaDIrectory");
newDir = new File(outFileName);
newDir.mkdir();
if(newDir.exists()) {
if (newDir.isDirectory()) {
Log.v("isDIrectory", newDir.toString());
}
}
} else {
Log.v(TAG, "NOTaDIrectory");
}
File outFileName1Dir = new File(outFileName1);
if (!outFileName1Dir.isDirectory()) {
newDir = new File(outFileName);
newDir.mkdir();
if(newDir.exists()) {
if (newDir.isDirectory()) {
Log.v("isDIrectory", newDir.toString());
}
}
} else {
Log.v(TAG, "ISaDIrectory");
}
Log.v(TAG, outFileName + dbname);
File file = new File(outFileName + dbname);
// File file = myContext.getFileStreamPath(dbname);
Log.v(TAG, "" + file.getPath() + " - " + file.getTotalSpace());
Log.v(TAG, outFileName + dbname);
File ff = new File(outFileName , dbname);
if (ff.exists()) {
Log.v(TAG, "FF -----------EXISTS");
}
String[] files = myContext.fileList();
for (String file1 : files) {
Log.v(TAG, file1.toString());
if (file1.equals(dbname)) {
Log.v(TAG, "FILE EXISTS");
}
}
if (file.exists()) {
Log.v(TAG, "FILE EXISTS");
if(file.isFile()) {
Log.v(TAG, "isFILE");
// return;
}
} else {
Log.v(TAG, "NO FILE");
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
Log.v(TAG, "Copying DB");
}
Log.v("FileExists", "" + file.createNewFile());
Log.v("FileWriteAble", "" + file.canWrite());
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
if (!file.canWrite()) {
Log.v("FileExists", "" + file.setWritable(true));
}
Log.v(TAG, "" + file.getPath() + " - " + file.getTotalSpace());
}
}
我知道...它是一堆代码,但有些人会要求查看它....
只是似乎无法解决这个问题。
MainActivity 中调用此函数的一些基本代码:
public class MainActivity extends FragmentActivity {
Context myContext;
String DB_PATH = null;
String DB_NAME = null;
public static ContextWrapper cw = null;
public static String PACKAGE_NAME;
之后,调用和其他一些定义:**大多数注释行用于尝试和完成此任务的不同尝试......
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myContext = getApplicationContext();
// ContextWrapper
cw = new ContextWrapper(getApplicationContext());
// DB_PATH =cw.getFilesDir().getAbsolutePath()+ "/Database/";
DB_NAME = "dates1.sqlite";
// DB_PATH = cw.getFilesDir().getAbsolutePath().replace("files", "Databases/"); // + "/Database/";
/* DB_PATH = destPath.substring(0, destPath.lastIndexOf("/")) + "/databases";
Log.v(TAG, DB_PATH);
*/
// get package name from anywhere
PACKAGE_NAME = getApplicationContext().getPackageName();
/* DbHelperNew dbNew = new DbHelperNew(cw, DB_NAME, null, 1);
Boolean T = dbNew.checkDataBase();
Log.v(TAG, T.toString());
*/
String[] files = this.fileList();
for (String file : files) {
Log.v(TAG, file.toString());
if (file.equals(DB_NAME)) {
Log.v(TAG, "FILE EXISTS");
}
}
try {
DbUtils.copyDataBase(DB_NAME, myContext);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// DbUtils.copyDataBase(DB_NAME, DB_PATH, myContext);
/* File src = new File("file:///android_asset/" + DB_NAME);
File dest = new File(DB_PATH + DB_NAME);
DbUtils.movedb(src, dest);
*/
for (String file : files) {
Log.v(TAG + "SECOND", file.toString());
if (file.equals(DB_NAME)) {
Log.v(TAG, "FILE EXISTS");
}
}
/* END */
_dbHelper = new DbHelper(getApplicationContext());
db = _dbHelper.getReadableDatabase();
我为凌乱的代码道歉......只是为了展示不同的尝试......
错误消息:
09-23 09:21:45.609: V/DbUtils(12851): Copying DB
09-23 09:21:45.621: W/System.err(12851): java.io.IOException: open failed: ENOTDIR (Not a directory)
09-23 09:21:45.628: W/System.err(12851): at java.io.File.createNewFile(File.java:940)
09-23 09:21:45.640: W/System.err(12851): Caused by: libcore.io.ErrnoException: open failed: ENOTDIR (Not a directory)
09-23 09:21:45.699: E/SQLiteOpenHelper(12851): Couldn't open dates1.sqlite for writing (will try read-only):
09-23 09:21:45.699: E/SQLiteOpenHelper(12851): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
09-23 09:21:45.707: E/SQLiteLog(12851): (14) cannot open file at line 30174 of [00bb9c9ce4]
09-23 09:21:45.707: E/SQLiteLog(12851): (14) os_unix.c:30174: (20) open(/data/data/com.ndroidians.listfrag/databases/dates1.sqlite) -
09-23 09:21:45.710: E/SQLiteDatabase(12851): Failed to open database '/data/data/com.ndroidians.listfrag/databases/dates1.sqlite'.
09-23 09:21:45.710: E/SQLiteDatabase(12851): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
为了解决不同的错误问题,我做了:
- 尝试不同的目录,公司:不同操作系统版本的代码,不同的文件夹/包访问代码,创建目录。
- 将文件扩展名从 */db 更改为 *.sqlite
- 将 assets 文件夹中的文件权限更改为 777
- 尝试了不同的复制功能
- 试过不同的手机
我可能在此过程中忘记了一些东西,但我已经花了 2 天的时间来完成这个简单(看似)的任务......
帮助....
编辑
更多信息:
我已经按照建议尝试了 chown ......仍然遇到同样的错误:
模拟器(这次)
>= 4.2 API17
New database is being copied to device! dates1.sqlite
New database has been copied to device!
chown 10054:10054 /data/data/com.ndroidians.listfrag/databases/dates1.sqlite
AFTER PROCESS
(14) cannot open file at line 30176 of [00bb9c9ce4]
(14) os_unix.c:30176: (20) open(/data/data/com.ndroidians.listfrag/databases/dates1.sqlite) -
Failed to open database '/data/data/com.ndroidians.listfrag/databases/dates1.sqlite'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
有趣的是,在模拟器上它显示数据库文件夹不是文件夹,而是一种文件......我附上一张图片......
另一方面,在设备上,它在 App Info 中将数据显示为正确的大小。我附上屏幕截图....
这是个谜……有人吗???