android内部存储外部存储以及assets文件的操作一些操作

这篇博客探讨了在Android应用中操作内部存储和外部存储的区别,特别是在真机上外部存储需要root权限的情况。作者强调内部存储无须root即可访问,并提供了相关代码示例,包括使用`getFilesDir()`获取内部存储路径以及创建自定义路径的方法。同时,还分享了关于Android文件下载、安装及访问私有文件的相关资源链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于项目需求,需要在应用本身的包中进行操作,其他程序是无法访问。既然是应用本身包中,那应该就是内部存储。

在模拟器上是无法体现内部存储和外部存储效果的。因为外部存储也可以实现。但是在真机上,外部存储就不能操作。这个需要root权限。没有root权限,是无法操作的。

内部存储是不需要root权限的,直接有路径就可以操作,因为为了实现功能,我测试了很多方法,最后才成功。

接下来就是代码,具体内容在代码注释中体现。


如果读写存储时,直接给定路径,例如直接写成死的:data/data/com.package.name/aaa...的话,这样就是外部存储,没有root权限好像是不能访问的。

如果想要写在自己应用本身的内部下,那就是内部存储,这样调用是不需要root。

这时候就有一个方法,getFIleDir() 获得的路径是data/data/包名/files路径。如果想要自定义路径,在下面的具体代码中有实现。请参考。

getFileDir()这个方法本身获得的就是内部存储,看一下开发文档的内容翻译如下:



/**
	 * 读取assets文件夹下的某个文件
	 * 你可以自己建一个txt文件,然后进行操作
	 */
	public void readAssets() {
		try {
			// assets文件夹下的文件
			InputStream is = getAssets().open(
					"applist/applist.preincluded.description");
			// 获得文件的内容大小
			int size = is.available();
			// 把这个大小给了存储数组的大小
			byte[] buffer = new byte[size];
			is.read(buffer);
			// 关闭流
			is.close();
			// 读取出来的正常内容(包括空格)
			String text = new String(buffer, "UTF-8");
			// 将读取出来的内容中的所有空格都替换掉
			String textResult = text.replace(" ", "");
			System.out.println(textResult);
			// 如果不换行输出,就显示不出来,不知道为什么
			// System.out.print(text);
		} catch (IOException e) {
			// Should never happen!
			throw new RuntimeException(e);
		}
	}


<span style="white-space:pre">	</span>try {
		ctxDealFile = this.createPackageContext("com.example.test",
				Context.CONTEXT_IGNORE_SECURITY);
	} catch (NameNotFoundException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
	 String uiFileName = "applist";
	deepFile(ctxDealFile, uiFileName);
	
	/** 上边的内容卸载onCreate中
	 * 遍历assets下的所有文件
	 * @param ctxDealFile
	 * @param path
	 */
	public void deepFile(Context ctxDealFile, String path) {
		try {
			String str[] = ctxDealFile.getAssets().list(path);
			if (str.length > 0) {// 如果是目录
				File file = new File("/data/" + path);
				file.mkdirs();
				for (String string : str) {
					path = path + "/" + string;
					System.out.println("zhoulc:\t" + path);
					// textView.setText(textView.getText()+"\t"+path+"\t");
					deepFile(ctxDealFile, path);
					path = path.substring(0, path.lastIndexOf('/'));
				}
			} else {// 如果是文件
				InputStream is = ctxDealFile.getAssets().open(path);
				FileOutputStream fos = new FileOutputStream(new File("/data/"
						+ path));
				byte[] buffer = new byte[1024];
				int count = 0;
				while (true) {
					count++;
					int len = is.read(buffer);
					if (len == -1) {
						break;
					}
					fos.write(buffer, 0, len);
				}
				is.close();
				fos.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

<span style="white-space:pre">	</span>/**
	 * 
	 * 将assets的文件写到固定目录下
	 */
	private void importDB() {
		File file = new File("data/data/com.example.test/",
				"applist/applist.preincluded.description");
		// String DbName = "people_db";
		// 判断是否存在
		if (file.exists() && file.length() > 0) {
		} else {
			// 使用AssetManager类来访问assets文件夹
			AssetManager asset = getAssets();
			InputStream is = null;
			FileOutputStream fos = null;
			try {
				is = asset.open("applist/applist.preincluded.description");
				fos = new FileOutputStream(file);
				int len = 0;
				byte[] buf = new byte[1024];
				while ((len = is.read(buf)) != -1) {
					fos.write(buf, 0, len);
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (is != null) {
						is.close();
					}
					if (fos != null) {
						fos.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

<span style="white-space:pre">	</span>/**
	 * 将assets文件夹的内容复制到固定目录下
	 * 
	 * @param myContext
	 * @param ASSETS_NAME要复制的文件名
	 * @param savePath 要保存的路径
	 * @param saveName 复制后的文件名
	 * 
	 * 参考:http://www.dewen.io/q/5544/
	 * 	 http://www.tuicool.com/articles/JNbqEj
	 */
	public static void copy(Context myContext, String ASSETS_NAME,
			String savePath, String saveName) {
		String filename = savePath + saveName;
		File dir = new File(savePath);
		// 如果目录不中存在,创建这个目录
		if (!dir.exists())
			dir.mkdirs();
		try {
			if (!(new File(filename)).exists()) {
				InputStream is = myContext.getResources().getAssets()
						.open(ASSETS_NAME);
				FileOutputStream fos = new FileOutputStream(filename);
				byte[] buffer = new byte[7168];
				int count = 0;
				while ((count = is.read(buffer)) > 0) {
					fos.write(buffer, 0, count);
				}
				fos.close();
				is.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

<span style="white-space:pre">		</span>imageView = (ImageView) findViewById(R.id.image);

		/**
		* 使用assets下的图片
		* http://www.2cto.com/kf/201408/322920.html
		*/
		InputStream is;
		try {
			is = this.getAssets().open("applist/applogo.png");
			Bitmap bmp = BitmapFactory.decodeStream(is);
			imageView.setImageBitmap(bmp);
		} catch (IOException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}

<span style="white-space:pre">	</span>/**
	 * 往固定的目录下的文件中写内容
	 * @param fileName 要操作的绝对路径/data/data/包名/路径+文件名
	 * @param write_str 要写入的内容
	 * @throws IOException
	 */
	public void writeSDFile(String fileName, String write_str)
			throws IOException {

		File file = new File(fileName);

		FileOutputStream fos = new FileOutputStream(file);

		FileOutputStream fos1 = openFileOutput(fileName,
				MainActivity.this.MODE_PRIVATE);

		byte[] bytes = write_str.getBytes();

		fos1.write(bytes);

		fos.close();
	}

	/**
	 * 读取固定目录下的文件(外部存储的操作。真机没有root是不可以的)
	 * @param fileName
	 * @return
	 * @throws IOException
	 * 参考博客:http://blog.csdn.net/ztp800201/article/details/7322110
	 */
	public String readSDFile(String fileName) throws IOException {

		File file = new File(fileName);
		// fileinputstream是不能传入路径的,只传入名称就找不到文件。所以需要传入file
		FileInputStream fis = new FileInputStream(file);

		FileInputStream fis1 = openFileInput(fileName);

		int length = fis1.available();

		byte[] buffer = new byte[length];
		fis1.read(buffer);

		String res = EncodingUtils.getString(buffer, "UTF-8");

		fis1.close();
		return res;
	}

<span style="white-space:pre">	</span>/**
	 * 内部存储的写方法
	 */
	public void writeNeibu() {
		String str = "测试内容111";
		// getFileDir()方法获得是file的路径,就是data/data/包名/file
		// 但是我想在自定义的路径下生成文件,我就获得file路径的父路径
		File dataDir = getFilesDir().getParentFile();
		File mydir = new File(dataDir, "aaa");
		// 创建data/data/包名/aaa路径
		mydir.mkdir();
		File file = new File(mydir, "test.txt");
		BufferedWriter bw = null;
		try {
			file.createNewFile();
			// fileoutputstream的第二个参数,就是决定是否追加 ,false为替换,true就会在尾部追加内容
			bw = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(file, false), "UTF-8"));
			// fw.append("测试内容");
			bw.write(str);
			bw.flush();
			bw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 内部存储的读方法
	 */
	public void readNeibu() {
		File dataDir = getFilesDir().getParentFile();
		File mydir = new File(dataDir, "aaa");
		File file = new File(mydir, "test.txt");
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					file), "UTF-8"));
			String str1 = null;
			int a;
			while ((a = br.read()) != -1) {
				str1 = br.readLine();
				System.out.println(str1);
			}
			br.close();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}


由于将apk下载到内部存储,安装时直接给路径,是无法调用的。因为外部不能调用应用内部文件,没有权限。

此时进行安装,就应该先将内部文件转移到外部,在从外部调用安装。

这里先用mkdir创建目录,在用createNewFile创建文件。

Button button = (Button) findViewById(R.id.button1);
		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					InputStream is = getAssets().open("abc.apk");
					File file = new File(Environment
							.getExternalStorageDirectory().getAbsolutePath()
							+ "/aaa");
					if (!file.exists()) {
						file.mkdir();
					}
					File file2 = new File(file, "abc.apk");
					if (!file2.exists()) {
						file2.createNewFile();
					}
					FileOutputStream fos = new FileOutputStream(file2);
					byte[] temp = new byte[1024];
					int i = 0;
					while ((i = is.read(temp)) > 0) {
						fos.write(temp, 0, i);
					}
					fos.close();
					is.close();
					Intent intent1 = new Intent(Intent.ACTION_VIEW);
					// Intent intent = new
					// Intent(Intent.ACTION_INSTALL_PACKAGE);
					intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					intent1.setDataAndType(Uri.parse("file://"
							+ Environment.getExternalStorageDirectory()
									.getAbsolutePath() + "/aaa/abc.apk"),
							"application/vnd.android.package-archive");
					startActivity(intent1);

				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});

		Button button2 = (Button) findViewById(R.id.button2);
		button2.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				File file = new File(Environment.getExternalStorageDirectory()
						.getAbsolutePath() + "/aaa/abc.apk");
				System.out.println("--->" + file.exists());
			}
		});



参考博客:

Android中关于内部存储的一些重要函数 :http://blog.csdn.net/hudashi/article/details/8037076

Android 开发之网络文件下载 :http://blog.sina.com.cn/s/blog_4c451e0e0101a8zd.html

appliacation私有文件访问--/data/data/packagename/ : http://aijiawang-126-com.iteye.com/blog/792931

Android中如何实现文件下载 : http://blog.sina.com.cn/s/blog_5f35912f0100zut7.html

Android程序中实现APK的安装 : http://blog.csdn.net/sunchaoenter/article/details/6683032

关于android 如何安装 assets文件下的apk : http://blog.csdn.net/shen332401890/article/details/8826827









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值