文章目录

  • 前言
  • 一、十六进制dat文件解析
  • 二、十六进制dat文件读操作
    • 1.读取手机中的dat文件数据
    • 2.修改dat文件
    • 3.获取U盘权限
    • 4.读写U盘dat文件
  • 总结
  • 参考文章

前言

大学毕业后来到公司的第一件工作就是通过U盘插入装有安卓系统的机器,通过U盘向机器设置设备码(下称SN)。一开始我的思路就是通过InStream先取到U盘里文件的数据,然后通过OutStream修改文件,然后把读出来的SN通过封装好的api接口发到机器上就完事。思路大体是对的,但是中间过程折磨了我这个新手好几天,接下来我将对其中的每一个环节进行分析。

一、十六进制dat文件解析

如果大家也有做到关于读取字节文件dat的,一定一定一定要问你的负责人要到关于dat文件的格式说明!!!不然会超级麻烦。话不多说,先展示一下我的dat文件的格式:

上述图片就是我用到的sn.dat文件。这里就不提我的摸索痛苦经历了,直接上结论。
首先最左边一列(“空格”前那一串数字)并不是我们会读取到的数据,我的理解是一种序号并且在你读写文件的时候并不会影响到,相当于是隐形的,简单来说就是可以不用管,这东西给你是方便看的。当然空格也是,实际上并没有空格,都是用来方便看的。然后最右边呢一串像乱码一样的东西也不用管,我的负责人跟我说是类似注解说明一样的东西,所以这个dat文件实际对我们有用的部分就是中间这一大块数据。
我这个dat文件是十六进制的形式,我们把每一行分为4组,每一组8个数。拿一行的第一组为例:803E0000 我先说结论,每两个数表示一个十六进制数,每4个十六进制数也就是一组代表一个数,我这里的数据采用的是小端结构,所以读出来就是"0x00、0x00、0x3E、0x80",换成十进制就是16000。解释一下,一个int型数据有4个字节,4byte就是32位,一个十六进制的数据(0x3E 这样)是8位,所以4个十六进制数就代表了一个int型的数。然后关于什么是小端结构,小端结构说白了就是低位写在前面,我们平时写的数据就是相反的大端结构,是高位写在前面。在硬件底层一般数据传输用的都是小端结构,通讯协议用的是大端结构。具体的详解可以百度大端、小端模式。

二、十六进制dat文件读操作

在读dat文件之前,我先说明一下我的文件格式,前4个字节存的是读到第几个SN号,9-12个字节存放的是SN号总数。然后从第六行开始,每8个字节为一组,前4个字节是标志位,0代表SN没用过,1代表已使用过;后4个字节才表示SN号。

1.读取手机中的dat文件数据

这里与一般读写文件的区别在于我们是需要读写字节文件,代码如下。

  public static void changeDat(File file) {FileInputStream inStream = null;FileOutputStream outStream = null;SNFileStream snFileStream = new SNFileStream();int dataPos = 0;//SN码到的使用位置int dataCount = 0;//SN码总数byte[] bytes = new byte[220 * 1024];//获取sn.dat内容int SNFlag = 0;//标志位int SNValue = 0;//设备号String StrSNValue = "";File newFile = new File("/mnt/shared/Pictures/sn2.dat");try {inStream = new FileInputStream(file);outStream = new FileOutputStream(newFile);} catch (FileNotFoundException e) {e.printStackTrace();}//getChannel()该方法的返回类型为FileChannel,它返回与此流连接的FileChannel。ReadableByteChannel inCh = inStream.getChannel();{//分配直接字符缓冲区ByteBuffer buffer = ByteBuffer.allocateDirect(16);//ByteOrder.LITTLE_ENDIAN表示小端模式buffer.order(ByteOrder.LITTLE_ENDIAN);int num = 0;while (true) {try {if (inCh.read(buffer) == -1) break;} catch (IOException e) {e.printStackTrace();}buffer.flip();bytes[num] = buffer.get();num++;buffer.compact();}//关闭FileInPutStreamtry {inStream.close();} catch (IOException e) {e.printStackTrace();}}

2.修改dat文件

把dat文件里的内容全部读出来存入byte数组后,拿出需要的数据并将需要修改的内容在byte数组中改,然后重新存入一个dat文件替代原来的文件,代码如下(接上)。

     //获取索引 4个byte代表一个32位的十六进制数byte[] mid = new byte[4];   //取32位十六进制数for (int i = 0; i < 4; i++) {mid[i] = bytes[i];}dataPos = snFileStream.byte2int(mid);Log.d("dataPos", String.valueOf(dataPos));//更新dataPosint updateDataPos = dataPos + 2;mid = snFileStream.int2byte(updateDataPos);for (int i = 0; i < 4; i++) {bytes[i] = mid[i];}//获取总数for (int i = 0; i < 4; i++) {mid[i] = bytes[i + 8];}dataCount = snFileStream.byte2int(mid);Log.d("dataCount", String.valueOf(dataCount));//获取SN码int SNValuePos = 4 + 8 * (dataPos - 1) + 80;for (int i = 0; i < 4; i++) {mid[i] = bytes[i + SNValuePos];}for (int i = 3; i >= 0; i++) {StrSNValue = StrSNValue.concat(DataTypeConvert.oneByte2TwoHexString(mid[i]));}Log.d("=-=-=-=-=-=-=-", StrSNValue);SNValue = snFileStream.byte2int(mid);Log.d("SNValue", String.valueOf(SNValue));//更新SN的标志位bytes[SNValuePos - 1] = 0x01;//把更新后的所有数据写入新dat文件中try {int length = bytes.length;Log.d("snLength", String.valueOf(length));outStream.write(bytes, 0, length);outStream.flush();outStream.close();} catch (IOException e) {e.printStackTrace();}Log.d("sn2.dat_Length", String.valueOf(newFile.length()));Log.d("sn1.dat_Length", String.valueOf(file.length()));//更新文件boolean successA = file.delete();if (successA) {Log.d("删除结果", "成功!!!");} else {Log.d("删除结果", "失败!!!");}File newFileName = new File("/mnt/shared/Pictures/sn.dat");boolean successB = newFile.renameTo(newFileName);if (successB)Log.d("重命名结果", "Success!!!");elseLog.d("重命名结果", "Fail!!!");}

这段代码里有用到两个转换函数,是用来把byte和int互相转换,两个函数如下。

    public static byte[] int2byte(int intValue) {byte[] b = new byte[4];for (int i = 0; i < 4; i++) {b[i] = (byte) (intValue >> 8 * i & 0xFF);//低位在前}return b;}public static int byte2int(byte[] b) {int intValue = 0;byte[] tempArray = new byte[4];for (int i = 0; i < b.length; i++) {tempArray[i] = b[i];}for (int i = 3; i >= 0; i--) {intValue |= (tempArray[i] & 0xFF) << (8 * i);}return intValue;}

以上就是在手机本地读取和存储dat文件的方法,接下来介绍一下U盘的读取。

3.获取U盘权限

首先在读取U盘文件之前,需要申请U盘权限(前面也别忘记写上权限,一并写这里了)

 <!--表示支持usb设备--><uses-feature android:name="android.hardware.usb.host" android:required="true"  /><uses-permission android:name="android.hardware.usb.host" android:required="false" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"tools:ignore="ProtectedPermissions" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在声明权限之后还需要动态获取U盘(USB设备的)的权限,然后用BroadcastReceiver根据接收到的不同广播去分别处理对应的事件,具体代码如下。

    //注册广播,监听otg插拔事件。public void registerReceiver() {IntentFilter usbDeviceStateFilter = new IntentFilter();//对应的USB设备插入的广播usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);//对应的USB设备拔出的广播usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);registerReceiver(mUsbReceiver, usbDeviceStateFilter);//注册监听自定义广播IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);registerReceiver(mUsbReceiver, filter);}//根据action,去分别处理对应的事件。BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case ACTION_USB_PERMISSION://接收到自定义广播synchronized (this) {UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { //允许权限申请if (usbDevice != null) {//读取所有设备read(getUsbMass(usbDevice));}} else {ToastUtil.showLongToast(SystemInfoActivity.this, "用户未授权,读取失败");}}break;case UsbManager.ACTION_USB_DEVICE_ATTACHED://接收到存储设备插入广播UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device_add != null) {ToastUtil.showLongToast(SystemInfoActivity.this, "接收到存储设备插入广播");listDevice();}break;case UsbManager.ACTION_USB_DEVICE_DETACHED://接收到存储设备拔出广播UsbDevice device_remove = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device_remove != null) {ToastUtil.showLongToast(SystemInfoActivity.this, "接收到存储设备拔出广播");usbFile = null;}break;}}};

其中对应的事件为read()和listDevice()方法,代码如下。

    //读取USB设备的根目录public void read(UsbMassStorageDevice massDevice) {try {massDevice.init();//初始化Partition partition = massDevice.getPartitions().get(0);FileSystem currentFs = partition.getFileSystem();UsbFile root = currentFs.getRootDirectory();//获取根目录usbFile = root;} catch (Exception e) {e.printStackTrace();ToastUtil.showLongToast(SystemInfoActivity.this, "读取失败");}}public void listDevice() {//获取管理者UsbManager usbManager = (UsbManager) getContext().getSystemService(Context.USB_SERVICE);//枚举设备storageDevices = UsbMassStorageDevice.getMassStorageDevices(getContext());//获取存储设备PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);for (UsbMassStorageDevice device : storageDevices) {//可能有几个 一般只有一个 因为大部分手机只有1个otg插口if (usbManager.hasPermission(device.getUsbDevice())) {//有就直接读取设备是否有权限read(device);} else {//没有就去发起意图申请usbManager.requestPermission(device.getUsbDevice(), pendingIntent); //该代码执行后,系统弹出一个对话框}}}//获取USB设备private UsbMassStorageDevice getUsbMass(UsbDevice usbDevice) {for (UsbMassStorageDevice device : storageDevices) {if (usbDevice.equals(device.getUsbDevice())) {return device;}}return null;}

4.读写U盘dat文件

接下来就相对简单了,直接看代码。

    //把本地文件写入到U盘中public static void saveSDFile2OTG(File file, UsbFile usbFile) {UsbFile usbSNFile = null;//删除旧文件UsbFile[] usbFiles;try {usbFiles = usbFile.listFiles();if (usbFiles != null && usbFiles.length > 0) {for (UsbFile file1 : usbFiles) {if (file1.getName().equals("sn.dat")) {file1.delete();  //删除U盘旧的sn.datbreak;}}usbSNFile = usbFile.createFile(file.getName());}} catch (IOException e) {e.printStackTrace();}try {OutputStream os = new UsbFileOutputStream(usbSNFile);FileInputStream is = new FileInputStream(file);int bytesRead = 0;byte[] buffer = new byte[1024 * 8];while ((bytesRead = is.read(buffer)) != -1) {os.write(buffer);}os.flush();os.close();is.close();} catch (Exception e) {e.printStackTrace();}file.delete();//删除本机sn文件}//把U盘文件写入到本地文件中public static void saveOTGFile2SD(File f, UsbFile usbFile) {try {FileOutputStream os = new FileOutputStream(f);InputStream is = new UsbFileInputStream(usbFile);int bytesRead = 0;byte[] buffer = new byte[1024 * 8];while ((bytesRead = is.read(buffer)) != -1) {os.write(buffer, 0, bytesRead);}os.flush();os.close();is.close();} catch (Exception e) {e.printStackTrace();}}

然后看一下Main函数,我稍微简化了一下。

    //本地存放路径private static final String SDFILEPATH = "/storage/emulated/0/sn.dat";//动态获取U盘权限registerReceiver();//这里必须先要list一下,为了弹出对话框手动允许获得U盘读写权限。listDevice();//U盘设置mBtnUdiskSetNum.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (usbFile != null) {try {int isHasSNfile = 0;//判断是否含有SN文件for (UsbFile file : usbFile.listFiles()) {if ("sn.dat".equals(file.getName())) {File sdfile = new File(SDFILEPATH);//在SD卡根目录创建一个临时sn.dat文件isHasSNfile = 1;new Thread(new Runnable() {@Overridepublic void run() {saveOTGFile2SD(sdfile, file);//把U盘文件存入SD卡try {//不停一下会报错,下同TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}udiskReadSn.udiskInsertSN(SDFILEPATH, isSuccess, SNValue);//注入SN并修改sn.dat文件try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}saveSDFile2OTG(sdfile, usbFile);//把修改好的sn.dat存回U盘}}).start();}Log.i(TAG, file.getName());}} catch (IOException e) {e.printStackTrace();}}}});

总结

以上就是全部关于U盘读取和写入dat数据文件的全部,新人创作,觉得不戳点个赞呗~

参考文章

Java实现.dat文件转txt可读文件
Android OTG 读写U盘文件
android OTG (USB读写,U盘读写)最全使用相关总结

【读写和修改U盘中的十六进制dat数据文件】相关推荐

  1. 关于python使用pandas导入dat数据文件的方法(可导入任意dat数据文件和csv数据文件)

    我相信大家在学习python中会遇到一些很苦恼的数据导入问题,csdn上面的数据导入五花八门,大多是在特定条件实行的数据导入,我在学习机器学习分类算法实现中发现csdn上面有很多dat数据文件,所以想 ...

  2. mysql 修改表空间名称_修改多个表空间的数据文件的名称和位置

    修改多个表空间的数据文件的名称和位置,可以在表空间级别,也可以在数据库级别进行. 在表空间级别进行就如同修改一个表空间数据文件的名称 和位置,一个一个的进行,直到全部完成. 在数据库级别,可以一次性的 ...

  3. mysql 下载到其他盘中_MYSQL 如果把数据文件保存到其他磁盘里

    今天在CSDN上有人问起分开存储数据文件的问题. 现在写下来. 为了突破磁盘搜索的瓶颈.我们要把MYSQL的数据和索引保存到其他不同的磁盘中.目前还只是支持MyISAM引擎.在MYSQL中,官这个叫象 ...

  4. Matlab读取Zygo干涉仪dat数据文件 光学检测加工(明码需另付费)

    本程序支持在Matlab中读取Zygo干涉仪/轮廓仪(MetroPro或Mx)的.dat测量文件. Zygo干涉仪和轮廓仪 一.结果图 直接上结果对比图.图为MetroPro和Matlab分别对同一个 ...

  5. 用Derby数据库读取加密的DAT数据文件(一)

    应某些需要,需要读取从Derby数据库中导出的dat加密文件.所以喽,现在手上有dat文件,要正确读取就要反过来. 后来发现需要开始做一些准备工作,比如:Derby的下载安装,环境的配置,必要时还要下 ...

  6. .dat数据文件怎么打开_SPSS统计分析,之一 SPSS数据文件读取

    简单地说,数据分析就是数据进行分析,从专业上说,数据分析就是依据分析目的,用适当的统计分析及工具,对收集来的数据进行处理与分析,提取有价值的信息,发挥数据作用,为企业的营销.战略的制定提供帮助和支持. ...

  7. java生成dat文件怎么打开_可以使用哪个软件工具打开Java程序生成的dat数据文件?...

    全部展开 .dat不是格式,任何格式的数据都可以.dat格式存储 您可以使用文本编辑器将其打开,以查看它是正常的文本数据格式还是其他编码格式,您可以使用相应的方法 没有软件可以100%打开所有DAT文 ...

  8. .dat数据文件怎么打开_CAXA线切割版,打开CAD的DWG, DXF文件的终极绝招

    经常会有朋友会问到这个问题,今天来解答一下,希望对大家有帮助.老鸟可以绕道,喜欢喷的请口下留情,谢谢! 年后东莞大朗一线切割操作师傅在微信上说,对我们这个机床文件无线传输装置很感兴趣,想了过来了解一下 ...

  9. .dat数据文件怎么打开_U盘坏了怎么恢复数据?恢复数据的方法

    相信大家对于U 盘来说也都并不陌生,在当前学习生活中, U盘可以说时候我们必备的一种数据存储工具,并且在使用和携带操作上,也都是相对比较方便的.但是很多人在使用过程中,常常伴随着一些特殊意外的情况, ...

最新文章

  1. hung-yi lee_p22_无监督学习:词嵌入
  2. MATLAB神经网络样本数量太大,MATLAB搭建bp神经网络的误差特别大,但R2的值也大,求解帮我看看我的网络哪里出问题了...
  3. 玩转Parse(第一篇:新手入门)
  4. 前谷歌高管给初入职场新人的14条忠告
  5. h5直播开发之旅总结
  6. 安卓端网页浏览过程中实时更新title的web实现
  7. cannot import name ‘softmax‘ from ‘scipy.special‘
  8. 读取oracle注释
  9. Mongodb源码分析--Replication之主从模式--Master
  10. 利用优盘安装win2008r2系统
  11. IDEA基于kotlin开发android程序配置小结
  12. 纯函数式编程语言_纯功能编程语言如何改变您的生活。
  13. STC51-l2C总线
  14. 不论报任何错误 都是网络源有问题,安装spacemacs报错的解决方式
  15. 系统分析与设计-我爱烤鱼创新过程与UP过程对比分析之我见
  16. 测试和维修电脑软件,常用的电脑维修软件有哪些?
  17. 银行软开开发篇[转]
  18. 历史上的今天:乔布斯辞去苹果CEO一职;Windows 95 发布
  19. 如何把微信消息或者短信实时转发到另一个手机上
  20. 相关系数(Correlation)

热门文章

  1. 做一个支持图形界面的操作系统(上)
  2. 黑马程序员_集合总篇_基础之重点
  3. MySQL使用FROM_UNIXTIME将时间戳格式化输出显示
  4. Invitation Cards——正反最短路
  5. 双向广搜的DIJKSTRA算法--简易的北京地铁导航实现
  6. 用rm递归删除子目录下所有.o后缀文件
  7. 忘记密码怎么办?如何查看网页上保存的密码
  8. ABAP--使用SLIN事务码进行ABAP程序扩展语法检查,提高程序开发的质量[转]
  9. 安卓APK文件的icon图标文件获取 xml格式
  10. MobData研究院,一个操作让游戏 营销ROI 翻了3倍