java 实际应用_Java IO在实际开发中的应用

IO是java绕不过去的槛,在开发中io无处不在, 正如同 世界上本没有路,java io写多了,也就知道了大体是什么意思,在读完thinking in java 感觉就更清晰了,结合具体的业务场景,整理一下 ,什么是IO。为什么JAVA要这么设计IO。

先来一道开胃菜

我想要读取控制台输入的字符

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 InputStreamReader isr = newInputStreamReader(System.in);2 BufferedReader br = newBufferedReader(isr);3 String s = null;4 try{5 System.out.println("开始输入 。。。");6 s =br.readLine();7 while (s != null) {8 if (s.equalsIgnoreCase("yes")) {9 break;10 }11 System.out.println(s.toUpperCase());12 System.out.println("是否停止输入(yes/no)");13 s =br.readLine();14 }15 } catch(IOException e) {16 e.printStackTrace();17 }finally{18 if(br !=null){19 try{20 br.close();21 } catch(IOException e) {22 e.printStackTrace();23 }24 }25 if(isr != null){26 try{27 isr.close();28 } catch(IOException e) {29 e.printStackTrace();30 }31 }32 }33

View Code

解释一下:我从控制台读取一行字符,然后打印一下。这就是一个简单的流了。

整理一下: 就是我先 得到一个用于读取 控制台输入的流,然后 我·打印我得到的东西,这里有个细节就是 流一定得关闭,这是底线,关闭的顺序:先声明的后关闭

稍微深入一点。我用Inputstream 去读取字符串并转化为想要的编码格式

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public staticString getStrFormInputStream(String str,2 String encoding) throwsIOException {3 InputStream inputStream = newByteArrayInputStream(str.getBytes(encoding));4 BufferedReader bf = null;5 InputStreamReader inputStreamReader = null;6 try{7 inputStreamReader = newInputStreamReader(inputStream);8 bf = newBufferedReader(inputStreamReader);9 StringBuffer sb = newStringBuffer();10 String line = "";11 while ((line = bf.readLine()) != null) {12 sb.append(line);13 }14 returnsb.toString();15 } finally{16 if (bf != null) {17 bf.close();18 }19 if (inputStreamReader != null) {20 inputStreamReader.close();21 }22 if (inputStream != null) {23 inputStream.close();24 }25 }26

27 }

View Code

这就偏实际一点,当你拿到一个字符串的时候,读取的时候,有一个细节:最好加上编码格式

解释一下:实际上读取的地方 只有这一点 line = bf.readLine() ,那么之前的是做什么呢,  我其实是在组装我想要的铲子。这也是 开发中比较常用的“包装器模式”

我想把字符串转为贴合实际的ByteArrayInputStream, 再转化为更常用的Reader(InputStreamReader)  再包装上buffer(BufferedReader)。

当我选择输出的时候:

当我查看我以前的开发记录时,发现实际业务中 绝大多数输出都是输出到文件的。想找一个简单的输出示例,并不容易

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public voidsendMessage(String str,2 String host,3 int port) throwsUnsupportedEncodingException, IOException {4 String sendEncoding = "GBK";5 Writer writer = null;6 Socket client = null;7 try{8 //与服务端建立连接

9 client = newSocket(host, port);10 //建立连接后就可以往服务端写数据了

11 writer = newOutputStreamWriter(client.getOutputStream(), sendEncoding);12 System.out.println(str);13 writer.write(str);14 writer.flush();//写完后要记得flush

15 } finally{16 if (writer != null) {17 try{18 writer.close();19 } catch(Exception e) {20 e.printStackTrace();21 }22 }23 if (client != null) {24 try{25 client.close();26 } catch(Exception e) {27 e.printStackTrace();28 }29 }30 }31

32 }

View Code

输出的地方其实很简单:writer.write(str); 其他的地方 建立服务器连接,将str写到短信中和此处关系不大,需要注意 :无论是输入输出,用完了一定关闭流,这是底线

我有一文件

文件读写才是一个真正的业务场景中占比绝大多数的。

文件的基本操作

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

String filePath = "D:\\";

File file= newFile(filePath);long length = 0;if(file.exists()){

length=file.length();

}else{

file.mkdirs();

}

View Code

在java中File 就是 File , 它既可以是具体的文件,也可以是一个文件目录

读写文件总体步骤

当你读写文件的时候,看到直接读取字节实际上应用更广一点,当然用读取字符也是占很大比重,所以,这个问题就丢给各位读者,到底是想用哪个。反正都行。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public byte[] getBytesByFileName(String filePath) {byte[] buffer = null;try{

File file= newFile(filePath);

FileInputStream fis= newFileInputStream(file);

ByteArrayOutputStream bos= new ByteArrayOutputStream(1000);byte[] b = new byte[1000];intn;while ((n = fis.read(b)) != -1) {

bos.write(b,0, n);

}

bos.close();

buffer=bos.toByteArray();

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}returnbuffer;

}

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static voidmoveFile(String sourcePath,

String targetPath)throwsException {

File sourceRoot= newFile(sourcePath);if (!sourceRoot.exists()) {throw new Exception("要移动的文件不存在");

}if(sourceRoot.isFile()) {boolean success = true;

File targetFile= newFile(targetPath);if (!targetFile.getParentFile().exists()) {if (!targetFile.getParentFile().mkdirs()) {

success= false;

}

}if (!targetFile.exists()) {if (!targetFile.createNewFile()) {

success= false;

}

}if (!success) {throw new Exception("目标目录创建失败");

}

BufferedInputStream bis= null;

BufferedOutputStream bos= null;byte[] d = new byte[1024];int length = -1;try{

bis= new BufferedInputStream(newFileInputStream(sourceRoot));

bos= new BufferedOutputStream(newFileOutputStream(targetFile));while ((length = bis.read(d)) != -1) {

bos.write(d,0, length);

}

bos.flush();

}catch(IOException e) {

e.printStackTrace();

success= false;

}finally{if (bos != null) {

bos.close();

}if (bis != null) {

bis.close();

}

bos= null;

bis= null;

}if(success) {

sourceRoot.deleteOnExit();

}

}else{

File[] files=sourceRoot.listFiles();for(File file : files) {

moveFile(file.getAbsolutePath(), targetPath+ File.separator +file.getName());

}

sourceRoot.deleteOnExit();

}

}

View Code

移动文件:实际上就是从一个文件中读取文件,然后写到另一个文件中,这算是一个非常详细的例子。分析代码:我想判断源文件是否存在,我再去创建目标文件夹和目标文件,当然,你也可以不用mkdir()

直接用 mkdirs()也行。

当然我写文件时的数据(调用write()方法传入的数据)不一定是来自文件也有可能来自一个list,一个byte[]数组。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public voidwriteFile(String str,

File file)throwsIOException {

OutputStream out= null;try{

out= new FileOutputStream(file, true); //是否追加

byte[] b =str.getBytes();

out.write(b);

out.flush();

}catch(Exception e) {

e.printStackTrace();

}finally{if (out != null) {

out.close();

}

}

}

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public void exportByModel(List>data,byte[] exportModel,

String fileNameLocation)throwsException {

InputStream in= null;

Reader reader= null;

OutputStream out= null;

Writer des= null;

CharArrayWriter writer= null;try{//读取模板

in = newByteArrayInputStream(exportModel);

reader= newInputStreamReader(in);//设置输出位置

out = newFileOutputStream(fileNameLocation);

String encoding= "GBK";try{

des= new OutputStreamWriter(out, encoding);//不设置utf-8,中文不支持

} catch(Exception e) {

des= new OutputStreamWriter(out, "GBK");//编码设置异常,直接按照GBK输出

}//执行

writer =VelocityHelper.getInstance().evaluateToWriter(data, reader);

writer.writeTo(des);

des.flush();

}catch(Exception e) {throw new Exception("写入文件异常");

}finally{if (writer != null)

writer.close();if (des != null)

des.close();if (out != null)

out.close();if (reader != null)

reader.close();if (in != null)

in.close();

}

}

View Code

读写图片

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public voidcreateImage(BufferedImage image,2 String fileLocation) throwsIOException {3 FileOutputStream fos = null;4 BufferedOutputStream bos = null;5 try{6 fos = newFileOutputStream(fileLocation);7 bos = newBufferedOutputStream(fos);8 //JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);9 //encoder.encode(image);

10 ImageIO.write(image, "JPEG", bos);11 } catch(Exception e) {12 e.printStackTrace();13 } finally{14 if (fos != null) {15 fos.close();16 }17 if (bos != null) {18 bos.close();19 }20 }21 }

View Code

1 boolean isJob =etlTrans.getFromKjb();2 byte[] xml =etlTrans.getXml();3 ByteArrayInputStream bais = newByteArrayInputStream(xml);4 TransMeta transMeta = null;5 JobMeta jobMeta = null;6 int imageWidth = 1400;//图片的宽度

7 int imageHeight = 900;//图片的高度

8 int wordWidth = 6;9 BufferedImage image = newBufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);10 Graphics graphics =image.getGraphics();11 //字体不支持时,中文就显示口口口了

12 graphics.setFont(new java.awt.Font("宋体", java.awt.Font.BOLD, 20));13 //Font oldFont = graphics.getFont();

14 graphics.setColor(Color.WHITE);15 graphics.fillRect(0, 0, imageWidth, imageHeight);

读写xml文件

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static voidobjectXmlEncoder(Object obj,

String fileName)throwsFileNotFoundException, IOException, Exception {//创建输出文件

File fo = newFile(fileName);//文件不存在,就创建该文件

if (!fo.exists()) {//先创建文件的目录

String path = fileName.substring(0, fileName.lastIndexOf('.'));

File pFile= newFile(path);

pFile.mkdirs();

}//创建文件输出流

FileOutputStream fos = newFileOutputStream(fo);//创建XML文件对象输出类实例

XMLEncoder encoder = newXMLEncoder(fos);//对象序列化输出到XML文件

encoder.writeObject(obj);

encoder.flush();//关闭序列化工具

encoder.close();//关闭输出流

fos.close();

}

View Code

xml文件读写,实际上也是一样的,只不过调用的是xml提供的读写工具类

分文件写数据

1 private voidwriteLog(FileOutputStream writer,2 List cellExceptionLogs) throwsIOException {3 StringBuilder builder = newStringBuilder();4 int len =cellExceptionLogs.size();5 for (int i = 0; i < len; i++) {6 ExceptionLog exceptionLog =cellExceptionLogs.get(i);7 processSystemLogData(exceptionLog, builder);8 if ((i + 1) % 500 == 0) {9 writer.write(builder.toString().getBytes("UTF-8"));10 writer.flush();11 builder = null;12 builder = newStringBuilder();13 }14 }15 if (len % 500 != 0) {16 writer.write(builder.toString().getBytes("UTF-8"));17 writer.flush();18 }19 }20 private voidprocessSystemLogData(ICellExceptionLog exception,21 StringBuilder builder) {22 builder.append(exception.getId() +Constant.REPORTUNITSEPARATOR);23 builder.append(exception.getCode() +Constant.REPORTUNITSEPARATOR);24 builder.append(exception.getName() +Constant.REPORTUNITSEPARATOR);25 builder.append(exception.getDescription()+Constant.REPORTUNITSEPARATOR);26 builder.append("\r\n");27 }

综合应用:编写一个页面,提供给用户下载数据。用户选择下载位置

本质上是一样,只不过输出的流特殊一点(参考于

第一步:写一个提供给用户的按钮

压缩包

第二步:编写对应的servlet方法。一共分两步:把文件读入文件流,把文件流内的数据写入到response中(response.getOutputStream().write(bytes, 0, bytes.length);)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

protected void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {//获得请求文件名

String filename = request.getParameter("filename");

System.out.println(filename);//设置文件MIME类型

response.setContentType(getServletContext().getMimeType(filename));//设置Content-Disposition

response.setHeader("Content-Disposition", "attachment;filename="+filename);//读取目标文件,通过response将目标文件写到客户端//获取目标文件的绝对路径

String fullFileName = getServletContext().getRealPath("/download/" +filename);//System.out.println(fullFileName);//读取文件

InputStream in = newFileInputStream(fullFileName);

OutputStream out=response.getOutputStream();//写文件

intb;while((b=in.read())!= -1)

{

out.write(b);

}

· in.close();

out.close();

}

View Code

断点续传

所谓断点续传 就是文件已经下载的地方开始继续下载。所以在客户端浏览器传给 Web服务器的时候要多加一条信息--从哪里开始。

断点续传的简单实例:

这是浏览器想要断点续传的时候发给服务器的信息

//GET /down.zip HTTP/1.0//User-Agent: NetFox//RANGE: bytes=2000070-//Accept: text/html, image/gif, image/jpeg, *; q=.2, *; q=.2//上边的信息,是浏览器发给web用户的断点续传的信息

服务器的操作: 这是一段简单的模拟从一定位置些文件的代码

//假设从 2000070 处开始保存文件,代码如下:

RandomAccess oSavedFile = new RandomAccessFile("down.zip","rw");long nPos = 2000070;//定位文件指针到 nPos 位置

oSavedFile.seek(nPos);byte[] b = new byte[1024];intnRead;//从输入流中读入字节流,然后写到文件中

while((nRead=input.read(b,0,1024)) > 0)

{

oSavedFile.write(b,0,nRead);

实际上,sevlet断点续传肯定不是这么简单,但是总体思路一致,我犹豫好久,最终还是把真正用于web项目的断点续传的服务器操作贴出(虽然我已经去了大多数和断点续传无关的业务逻辑,但是代码还是稍显复杂)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public static final int buf_size = 8192;2 ServletOutputStream out =response.getOutputStream();3 RandomAccessFile raf = null;4 File file = null;5 try{6 file = new File(filefullname);//这是我们写文件的数据来源

7 raf = new RandomAccessFile(file, "rw");8 long pos = 0;9 long end = 0;//这写开始写的位置,结束的位置可以从请求报文得到

10 long fLength =file.length();11 //如果有断点续传的信息

12 if (queryStringMap.get("Range") != null) {13 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//设置返回信息为206

14 String range = ((String) queryStringMap.get("Range")).replaceAll("bytes=", "");15 pos = Long.valueOf(range.split("-")[0]);16 end = Long.valueOf(range.split("-")[1]);17 } else{18 end = fLength - 1;19 }20 //是我这次请求需要写多少长度的文件

21 long length = end - pos + 1;22 //下面是返回报文信息

23 response.setHeader("Content-Length", String.valueOf(length));24 response.setContentType("application/x-msdownload");25 response.addHeader("content-disposition", "attachment;filename=\"" + filename + "\"");26 //下边是调用RandomAccess方法进行断点续传

27 byte[] buf = new byte[buf_size];28 int n = 0;29 int i = 0;//用来for循环中统计写的次数

30 raf.seek(pos);//定位文件指针到 pos 位置31 //buf_size 是定义的大文件写的快,如果你的文件还没一块大,直接写就好

32 int p = (int) (length / buf_size);//我要写多少块(byte[])

33 int b_size = (int) (length %buf_size);34 if (b_size > 0)35 p++;36 while (i

0) {39 buf = new byte[b_size];40 n = raf.read(buf, 0, b_size);41 } else{42 n = raf.read(buf, 0, buf_size);43 }44 out.write(buf);45 pos +=n;46 raf.seek(pos);47 }48 }catch(Exception e){49 e.printStackTrace();50 }finally{51 //....

52 }53 //...

54

View Code

服务器操作完成之后返回的相应信息: 可以清楚的看到比普通的返回信息多了一个content-range

//Content-Length=106786028//Content-Range=bytes 2000070-106786027/106786028//Date=Mon, 30 Apr 2001 12:55:20 GMT//ETag=W/"02ca57e173c11:95b"//Content-Type=application/octet-stream//Server=Microsoft-IIS/5.0//Last-Modified=Mon, 30 Apr 2001 12:55:20 GMT

RandomAccessFile的常用方法介绍 可以参考java的RandomAccessFile类

给你一数据库

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 protected MapgetRecord(ResultSet rset,2 ResultSetMetaData metaData,3 int colnum) throwsSQLException {4 Map resultMap = new HashMap();5 for (int columnCount = 1; columnCount <= colnum; columnCount++) {6 String aliasName =metaData.getColumnLabel(columnCount);7 Object columnValue = null;8 String columnName = aliasName != null ?aliasName : metaData.getColumnName(columnCount);9 int columnType =metaData.getColumnType(columnCount);10 //...

11 if (columnType == Types.BLOB || columnType ==Types.LONGVARCHAR12 || columnType ==Types.LONGVARBINARY) {13 if (rset.getBlob(columnName) != null) {14

15 InputStream res =rset.getBlob(columnName).getBinaryStream();16 int BUFFER_SIZE = 4096;17 ByteArrayOutputStream outStream = newByteArrayOutputStream();18 try{19 byte[] data = new byte[4096];20 int count = -1;21 while ((count = res.read(data, 0, BUFFER_SIZE)) != -1)22 outStream.write(data, 0, count);23

24 data = null;25 columnValue = newString(outStream.toByteArray());26

27 } catch(Exception e) {28 throw new SQLException("GenericDaoImpl.jdbc.error");29 } finally{30 try{31 if (outStream != null)32 outStream.close();33 if (res != null)34 res.close();35 } catch(IOException e) {36 throw new SQLException("GenericDaoImpl.jdbc.error");37 }38 }39 }40 } else if (columnType ==Types.CLOB) {41 Clob clob =rset.getClob(columnName);42 if (clob != null) {43 columnValue = clob.getSubString((long) 1, (int) clob.length());44 }45 } else{46 columnValue =rset.getObject(columnName);47 }48 resultMap.put(columnName.toUpperCase(), columnValue);49 }50 returnresultMap;51 }

数据库中读取记录代码

一般情况下,web项目采用一些orm框架足以支撑,数据库字段的读写,但是,有时候为了效率或者是特有的业务要求。会自己编写dao层支持。

而在读取数据库记录,写入Map的时候,如何读取一些特殊字段,比如Blob, 上述代码就是描述如何读取blob字段

IO概括:

文件的读写 ,在java中是非常常用。

而设计者设计读写控制的时候,也整理的颇为详细,可能的结果就是,给调用者带来很大的困惑,这么多类,咋用。

其实完全不用担心:java写文件只有三步,百变不离其宗

1:我找到三样东西:   铲子(IO工具类); 沙子(我要读取的数据); 篓子(我要放的东西)

2:用铲子把沙子放到篓子里

3:我把铲子还给人家

至于我用 何种铲子,我要铲的是沙子 还是面粉,我要放到篓子还是框子里。先别管,也别上来就看那个javaIIO的类示意图

按铲子区分:一般单一的铲子不适用,需要组合多种功能

java中有读写字符的(reader/writer) 读写字节的(inputstream,outputstream)。自由选择

java按照功能 还会有 filereader xmlreder imgio   buffereader 等

按照沙子来看:

字符串,byte[] , List,数据库查询的结果集

按照篓子来看

可以放到Map String 图片 文件 xml

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值