使用字符流读取文件(非文本)以java的字符流读取文件为例:它只能读取0-65535之间的字符,可以看出来字符都是正数,但是二进制的byte是可以为负数的。但是读取的时候会被当做正数来读取,或者是无法在编码表中找到的字符会返回一个奇怪的符号(你可能见过那个奇怪的 “?”)。
但是在某些情况下,必须要使用字符来显示二进制数据,也不是没有办法的,下面就来介绍一个我们什么的方式–base64编码。
base64编码base64编码简介base64是网络上常见的用于传输8bit字节码的编码方式之一,base64就是一种基于64个可打印字符来表示二进制数据的方法。base64编码是从二进制到字符的过程,可以用在http环境下传递较长的标识信息。采用base64编码后具有不可读性,需要解码后才能阅读。它的中文名是基于64个可打印字符来表示二进制数据。
编码规则1. 把3个字节变成4个字节.
2. 没76个字符加一个换行符。
3. 最后的结束符也要处理。
编码方式的缺点从编码规则可以看出来,base64要求把每三个8bit的字节转换成四个6bit的字符(38 = 46 = 24),然后把6bit再添加两位高位0,组成四个8bit的字节。也就是说,转换后的字符串理论上将要比原来的长1/3(33%)。
这里这是介绍一个概念,关于更加详细的内容,如果感兴趣的话,可以取收集了解更多。
base64在 java 里的应用java的base64工具类提供了一套静态方法获取下面三种base64编解码器:
基本:输出被映射到一组字符a-za-z0-9+/,编码不添加任何行标,输出的解码仅支持a-za-z0-9+/。
url:输出映射到一组字符a-za-z0-9+_,输出是url和文件。
mime:输出隐射到mime友好格式。输出每行不超过76字符,并且使用’\r’并跟随’\n’作为分割。编码输出最后没有行分割。
分别对应如下几个方法:
encoder basicencoder = base64.getencoder();encoder mimeencoder = base64.getmimeencoder();encoder urlencoder = base64.geturlencoder();
我写了一个简单的工具类来进行测试 基本(basic) 的编码器。。
package com.dragon;import java.io.bufferedinputstream;import java.io.bytearrayoutputstream;import java.io.file;import java.io.fileinputstream;import java.io.filenotfoundexception;import java.io.ioexception;import java.io.inputstream;import java.io.unsupportedencodingexception;import java.util.base64;import java.util.base64.decoder;import java.util.base64.encoder;/** * @author alfred * */public class base64util { private static encoder encoder = base64.getencoder(); private static decoder decoder = base64.getdecoder(); private static string encode = "utf-8"; private static int length = 1024; /** * 静态方法: * 将文件等二进制数据(文本和非文本都可以) * 转为base64字符串。 * @throws ioexception * @throws filenotfoundexception * * */ public static string datatobase64(file src) throws filenotfoundexception, ioexception { encoder encoder = base64.getencoder(); int len = (int)src.length(); byte[] bar = new byte[(int)len]; int hasread = 0; byte[] b = new byte[length]; //使用专门处理 byte 的io流比较方便,一次性读取较大文件对内存压力较大 try (inputstream in = new bufferedinputstream(new fileinputstream(src)); bytearrayoutputstream bos = new bytearrayoutputstream(len)) { while ((hasread = in.read(b)) != -1) { bos.write(b, 0, hasread); } bar = bos.tobytearray(); } return encoder.encodetostring(bar); } public static string datatobase64(string src) throws unsupportedencodingexception { return encoder.encodetostring(src.getbytes(encode)); } public static byte[] base64todata(string src) { return decoder.decode(src); }}
将图片转为base64字符串进行读写import java.io.bufferedreader;import java.io.bufferedwriter;import java.io.file;import java.io.filenotfoundexception;import java.io.filereader;import java.io.filewriter;import java.io.ioexception;import java.io.unsupportedencodingexception;import java.io.writer;import java.nio.file.path;import java.nio.file.paths;public class base64test { public static void main(string[] args) throws filenotfoundexception, ioexception { testpic(); } static void testpic() throws filenotfoundexception, ioexception { // 测试图片文件。 path picpath = paths.get("./src/com/dragon/001.jpg"); file picfile = picpath.tofile(); string pictobase64 = base64util.datatobase64(picfile); system.out.println(pictobase64); long oldsize = picfile.length(); long newsize = pictobase64.getbytes("utf-8").length; system.out.println("图片原始大小(字节):" + oldsize); system.out.println("转换后数据大小(字节):" + newsize); system.out.println("转换后比原来扩大的比例为:" + (double)(newsize-oldsize)/(double)oldsize + " %"); //将数据写入文件 try (writer writer = new bufferedwriter(new filewriter("./src/com/dragon/002.txt"))) { writer.write(pictobase64); } //从文件中读取数据 string line = null; try (bufferedreader reader = new bufferedreader(new filereader("./src/com/dragon/002.txt"))){ line = reader.readline(); } system.out.println(pictobase64.equals(line)); }}
运行截图
说明:这里将图片转为base64字符串后,使用字符流写入了一个文本文件,然后再使用字符流读取出来,再和原来的字符串进行比较结果为 true。 所以,就完成了对图片数据的读取,可能你这里说你读取的并不是图片的二进制数据,但是其实所有的文件都是以二进制来存储的!而且,这个base64字符串,也是可以直接作为图片来使用的。
注意:我这里已经选取了一个非常小的图片,可以看到原始大小才 3639字节,也就是不到 4 kb,但是如果转换成文字那就是不少了(所以,它会显得很长,非常长。)。
测试图片
然后你可能会问怎么证明这个字符串就是上面这张图片呢?这个也很好办到,如果你对前端的知识有所了解的话,应该知道前端的图片是可以使用base64字符串来表示的,下面写一个 html 文件测试一下。
image.html
<!doctype><html> <head> <meta charset="utf-8"/> <title>base测试</title> </head> <body> <img src="data:image/jpeg;base64,/9j/4aaqskzjrgabaqaaaqabaad/2wbdaasicaoibwskcqondasnerwseq8pesizghqcksqrkigkjyctmka3lta9mccnoew5punfselikzzpvu5gvebhsex/2wbdaqwndrepeseseifflicuruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfruvfrux/waarcafgakqdasiaahebaxeb/8qaggabaqebaqebaaaaaaaaaaaaaambbgiebf/eadqqaqabawedcwqcagidaaaaaaabagqrawuhsriumtq1u1vzdjkkqvfhcrmigzejojlr8p/eabkbaqadaqeaaaaaaaaaaaaaaaabagmebf/eaciraqabagydaqeaaaaaaaaaaaacaredehmxuwehmjnbiv/aaawdaqaceqmrad8a+dembhk9k1hoajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahb6xz9h7ajhlwapz1h7ajhlxpld7wd86acruaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabxg9jc/dk9lpo8aasaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaao30ezrd01hcws0ez7d01hcwuew72sh5xafwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadh9/wbt9nx+womjwdeamg3ewcgbwaaaaaaaaaaaaaaaaaaaaaaaaaaaaadvo9n2hpqoetzo9nwhpqoetc8t3typziaktqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahetj6sxsxhky+rq/hgaf5cgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7fr7psptucjazs7psptucja55bvawfneavagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaohmzbipuyd0ul4dzjdasgmaaaaaaaaaaaad3gjq1uxnolqte74mkjmj/u4ezoqiumiaaorqmiimymjmz6mro+qyfx9appqxfutmte7piy6ymhuddwpnfwlqrojnftmboijmf8rmtp2ydwaaaaaaaaaaaaaaadt9hs+w9nrwlrnhs+w9nrwlrmlu9rb+dabduaaaaaaaaaaaabujmmxezgm5xuxngf9ik1swbyzzmcmcxummb4jpmomjj9xgl0yajaaaaaaaaaaaaaaaacrhjd7htr4aakaaaaaaaaaaaadnsilrttrauds9/ir0lmkqakqsrfmryete7onfopvkwzrmvtvbzxnwupr07fl6endurvxxiomzmn0rm5iixmcfl+ltfxvnmu03wvtterergrveredergwc7uf5f5junwdtk8nltqtm46czznh4rza793afxtgjytq13fxp6s016tgpb00fyrfcxmzvgzpndey+sft+3trnduxqutqtopqxfu6nm08mapmyz0zuommc/wqoneoi1l671qjp1brw1kzmjmmrumymy3xojl5m41qqqqp1dsaqscqzqnm4nmz3/sd/73otvf/lxqvtqaldu0xtm1tm0xgijm9gppjow84w2apqqmqqzmqzmzmzzmzptmsw83qaaaaaaaaaaaaaa7fr7psptucjazs7psptucja55bvawfnqavagaaaaaaaaaaad9o31p+cma6qacu8reto+mmr/jfe/fe/mbfvudfuxuxumejocjpwzoccz7orqp1rirummmyimnlrmxeznmb435wx1xk0645wcasfwzxun77v8aw58m1tmtmznm5nm5zp3bvqvvrevvvvrezmrmzo/7l/ctmo1bvp1gsq2gsaaaaaaaaaaaaaaacrmwdlzyzgxts8aasaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaao30ez7d01hcws0uz7d01hcwuew72sh50afwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadij/lm4bm5zhs6vx4aauaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahb6pz9h7ajhlwapz9h7ajhlxpld7wd86acruaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabxe4yf5hv+paj6qaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadvo9n2hpqoetzo9nwhpqoetc8t3typziaktqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahezhk9lcr92t0umlngacqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab2+j2dyemo4s1mj2dyemo4s1zy3e1g/oiaq1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafk42v4x8ioxsrwv5fsa0zvefpx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopc+nlef/iqmbk8l+ruggappx4xxsrwv5frjzxhfykkazvnopdrtdrttsztpjq5nmavmu08qz5my3rn6/t75tb9z/anpzz9qtfjp4lo/w0kfyjzw37mfdlea2/df9pvba3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90nnbfup90raw7r5rb91puk5rb91pulyc3apnbfup90iwfu3eadmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab2fn1c18mnguhzdqtfjp4li8puaquaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4gbleaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab2fn1c18mnguhz9qtfjp4li8puaquaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4gbleaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab2fn1c18mnguhz9qtfjp4li8puaquaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4gbleaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab2fn1c18mnguhz9qtfjp4li8puaquaaaaaaaaaaaabkadiaaaaaaaaaaaaaaaaaadiaesqaaaaaaaaaaabtr/gzm3e6srgmrpxe5++czh4tfra3c2lu10awnxxmjiqujmyjfmi+0zu3xvjaiuz6l62t9px0o0o1kk9wqjnqqim6dmzgimymctod0tviol9mps7qirup0tgote1uxxvpa1e6jmm5jezjht0pzueavotrq0wdealncvznwrvvmyno/p5u09qcivr1krwivu0qcrqtxvezoznoinh1n6suursr6dn2nrrwtnerp01tivfuvtezyfrmtvhtmoip3mpm2ohz3xp5ecnt0qzp06zmzrmrermzmejp3xnd46dpxnghoavgpxttptmf1qmovezgi/erjeftwraurvdzctte4oiimmqqzimimj6emczg/9l0wk+nawzre2t9xuoiqmy1jmngjjezerto/oxmy+uh4769fafdxbzo1aolfm4nnmtgjjdexgcbozgojfnpfilxv+gasaaaaaaaaaaaa7cz6ha+ttwxqs+owvk08fxehqaixaaaaaaaaaag6cuzxty/8ax+u9heztvtvezxmthkjeal16entfux0xmyxezeyj9/l5nsp5etvzim8mcz0z6jzvrzvtnpjiiqjezl4muqrevb6yxii3fjpt4y0jjx+oj+xuin/jxin9/wp9mppcmi/pvmr6rmzjf90/5jmqqqaynlyze9g7h/or1a64ikojmyxp1j7/aozwzzkzp6f9ojp9n0zysf8a32qh7/nrmkt8xypznltu/eq8fel4ultcavaaaaaaaaaaaaaaaoiasxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadhz9qtfjp4lowfulxyaec4vd1aelgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaoiasxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadhz9qtfjp4lowfulxyaec4vd1aelgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaoiasxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadhzdqtfjp4lowfulxyaec4vd1aelgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaoiasxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadhzdqtfjp4lowfulxyaec4vd1aelgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaoiasxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadhzdqtfjp4lglw9qbc4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad//z"/> </body><html>
打开浏览器测试一下
说明: 它的具体用法如下:
<img src="https://img-blog.csdnimg.cn/2022010703315790409.jpeg">
图片的大小相对于字符来说,其实是很庞大了。我这里的html代码是完整的图片的base64编码字符串,然后我的博客的字数就变大了很多。
字符串转base64编码public class base64test { public static void main(string[] args) throws filenotfoundexception, ioexception { teststr("i love you yesterday and today!"); } static void teststr(string src) throws unsupportedencodingexception { //测试文本数据。 string strtobase64 = base64util.datatobase64(src); system.out.println("base64编码:" + strtobase64); string base64tostr = new string(base64util.base64todata(strtobase64)); system.out.println("base64解码:" + base64tostr); }}
测试截图
base64的用处base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括mime的email,email via mime, 在xml中存储复杂数据。 注1:互联网上也有很多可以进行编解码的网站,如果需要使用的话,可以取尝试一下。
注2:可以观察一下这个base64字符串的特点,我上次学习java爬虫的时候,爬了一个网站,发现这个网站的一个 script 脚本中,含有一个json对象,其中有一个属性是 url,但是对应的链接却看不懂(base64字符串是不可读的),但是我感觉它就是base64字符串,所以我利用base64编解码网站解码一看,真的是一个网站的地址。然后,就可以写一个解码方法,当爬到这个数据时,给它解码了,哈哈。
举一个简单的例子:
{"url":"ahr0chmlm0elmkylmkz3d3cuymfpzhuuy29tjtjg"}
import java.io.unsupportedencodingexception;import java.net.urldecoder;import java.net.urlencoder;import java.util.base64;import java.util.base64.decoder;import java.util.base64.encoder;public class testalittle { public static void main(string[] args) throws unsupportedencodingexception { string base64str = "ahr0chmlm0elmkylmkz3d3cuymfpzhuuy29tjtjg"; string de_str = base64tourlencodertourl(base64str); system.out.println("解码:" + de_str); } //base64解密为urlencoder,再解码为url public static string base64tourlencodertourl(string base64str) throws unsupportedencodingexception { decoder decoder = base64.getdecoder(); byte[] bt = decoder.decode(base64str); string en_str = new string(bt, 0, bt.length); return urldecoder.decode(en_str, "utf-8"); }}
说明: 这个例子中的 url 进行了两次编码,第一次是将url中的非西欧字符编码(可以去了解一下为什么这么做?),然后再使用base64编码。但是,如果你掌握了解码技术,解码也是很简单的。(但是如果你看不出来它是base64编码,那估计就没有办法了!)
以上就是java怎么使用字符流读写非文本文件的详细内容。