File I/O source code--写入文件 相关方法阅读
2014-12-10 14:14
393 查看
测试例子:
我们从out.write( ... )来看,它首先会调用java.io.Write 类中的方法:
本来应该调用java.io.Write类中的write(String str, int off, int len)方法,但是BufferedWriter类中重写了这个方法,所以调用子类中重写的方法:
cb数组有了值后,我们再看flushBuffer()方法:
核心就在这里的out.write(cb, 0, nextChar) 我跟踪源代码发现会进入java.io.Writer类中的:
这里会调用java.io.OutputStreamWriter类中的方法(java.io.FileWriter继承java.io.OutputStreamWriter):
上面的这句话需要注意一下:CharBuffer cb = CharBuffer.wrap(cbuf, off, len); 解读意思就是讲数据放入字符缓冲区
看完flushBuffer();方法,我们再来看看out.flush();方法:
我们来看看implFlush()方法:
当程序执行到out.write(bb.array(), bb.arrayOffset() + pos, rem);这句的时候我不知道是在哪里实现的,断点老是进不去,纠结很久.........
第二天,重新梳理一遍: java.io.FileWriter的构造方法如下:
而我上面 用到的out对象是java.io.OutputStream,这里就很清楚了,我用到的肯定是java.io.FileOutputStream对象,那么为什么我断点进入不了呢,后来我把源码重新编译一次放入rt.jar包中,断点进入了 哈哈:
这里最终又用到了本地方法,这时java的任务算是告一段落,剩下的交给操作系统底层来完成了
/* 写入Txt文件 */ File writename = new File(".\\output.txt"); //相对路径,如果没有则要建立一个新的output。txt文件 writename.createNewFile(); // 创建新文件 BufferedWriter out = new BufferedWriter(new FileWriter(writename)); out.write("我会写入文件啦\r\n"); // \r\n即为换行 out.flush(); // 把缓存区内容压入文件 out.close(); // 最后记得关闭文件
我们从out.write( ... )来看,它首先会调用java.io.Write 类中的方法:
/** * Writes a string. * * @param str * String to be written * * @throws IOException * If an I/O error occurs */ public void write(String str) throws IOException { write(str, 0, str.length()); }
本来应该调用java.io.Write类中的write(String str, int off, int len)方法,但是BufferedWriter类中重写了这个方法,所以调用子类中重写的方法:
/** * Writes a portion of a String. * * <p> If the value of the <tt>len</tt> parameter is negative then no * characters are written. This is contrary to the specification of this * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int) * superclass}, which requires that an {@link IndexOutOfBoundsException} be * thrown. * * @param s String to be written * @param off Offset from which to start reading characters * @param len Number of characters to be written * * @exception IOException If an I/O error occurs */ public void write(String s, int off, int len) throws IOException { synchronized (lock) { ensureOpen(); int b = off, t = off + len; while (b < t) { int d = min(nChars - nextChar, t - b); s.getChars(b, b + d, cb, nextChar); b += d; nextChar += d; if (nextChar >= nChars) flushBuffer(); } } }注意看这里的s.getChar(b, b + d, cb, nextChar),本来这里的cb数组是空的,但是执行完这句后就有值了,原因我看了一下,是因为String的值会拆成数组然后赋值给cb数组:
/** * Copies characters from this string into the destination character * array. * <p> * The first character to be copied is at index <code>srcBegin</code>; * the last character to be copied is at index <code>srcEnd-1</code> * (thus the total number of characters to be copied is * <code>srcEnd-srcBegin</code>). The characters are copied into the * subarray of <code>dst</code> starting at index <code>dstBegin</code> * and ending at index: * <p><blockquote><pre> * dstbegin + (srcEnd-srcBegin) - 1 * </pre></blockquote> * * @param srcBegin index of the first character in the string * to copy. * @param srcEnd index after the last character in the string * to copy. * @param dst the destination array. * @param dstBegin the start offset in the destination array. * @exception IndexOutOfBoundsException If any of the following * is true: * <ul><li><code>srcBegin</code> is negative. * <li><code>srcBegin</code> is greater than <code>srcEnd</code> * <li><code>srcEnd</code> is greater than the length of this * string * <li><code>dstBegin</code> is negative * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than * <code>dst.length</code></ul> */ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } if (srcEnd > count) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } System.arraycopy(value, offset + srcBegin, dst, dstBegin, srcEnd - srcBegin); }
cb数组有了值后,我们再看flushBuffer()方法:
/** * Flushes the output buffer to the underlying character stream, without * flushing the stream itself. This method is non-private only so that it * may be invoked by PrintStream. */ void flushBuffer() throws IOException { synchronized (lock) { ensureOpen(); if (nextChar == 0) return; out.write(cb, 0, nextChar); nextChar = 0; } }
核心就在这里的out.write(cb, 0, nextChar) 我跟踪源代码发现会进入java.io.Writer类中的:
/** * Writes a portion of an array of characters. * * @param cbuf * Array of characters * * @param off * Offset from which to start writing characters * * @param len * Number of characters to write * * @throws IOException * If an I/O error occurs */ abstract public void write(char cbuf[], int off, int len) throws IOException;
这里会调用java.io.OutputStreamWriter类中的方法(java.io.FileWriter继承java.io.OutputStreamWriter):
/** * Writes a portion of an array of characters. * * @param cbuf Buffer of characters * @param off Offset from which to start writing characters * @param len Number of characters to write * * @exception IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { se.write(cbuf, off, len); }
public void write(char cbuf[], int off, int len) throws IOException { synchronized (lock) { ensureOpen(); if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } implWrite(cbuf, off, len); } }
void implWrite(char cbuf[], int off, int len) throws IOException { CharBuffer cb = CharBuffer.wrap(cbuf, off, len); if (haveLeftoverChar) flushLeftoverChar(cb, false); while (cb.hasRemaining()) { CoderResult cr = encoder.encode(cb, bb, false); if (cr.isUnderflow()) { assert (cb.remaining() <= 1) : cb.remaining(); if (cb.remaining() == 1) { haveLeftoverChar = true; leftoverChar = cb.get(); } break; } if (cr.isOverflow()) { assert bb.position() > 0; writeBytes(); continue; } cr.throwException(); } }
上面的这句话需要注意一下:CharBuffer cb = CharBuffer.wrap(cbuf, off, len); 解读意思就是讲数据放入字符缓冲区
/** * Wraps a char array into a buffer. * * <p> The new buffer will be backed by the given char array; * that is, modifications to the buffer will cause the array to be modified * and vice versa. The new buffer's capacity will be * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit * will be <tt>offset + length</tt>, and its mark will be undefined. Its * {@link #array </code>backing array<code>} will be the given array, and * its {@link #arrayOffset </code>array offset<code>} will be zero. </p> * * @param array * The array that will back the new buffer * * @param offset * The offset of the subarray to be used; must be non-negative and * no larger than <tt>array.length</tt>. The new buffer's position * will be set to this value. * * @param length * The length of the subarray to be used; * must be non-negative and no larger than * <tt>array.length - offset</tt>. * The new buffer's limit will be set to <tt>offset + length</tt>. * * @return The new char buffer * * @throws IndexOutOfBoundsException * If the preconditions on the <tt>offset</tt> and <tt>length</tt> * parameters do not hold */ public static CharBuffer wrap(char[] array, int offset, int length) { try { return new HeapCharBuffer(array, offset, length); } catch (IllegalArgumentException x) { throw new IndexOutOfBoundsException(); } }
看完flushBuffer();方法,我们再来看看out.flush();方法:
/** * Flushes the stream. * * @exception IOException If an I/O error occurs */ public void flush() throws IOException { se.flush(); }
public void flush() throws IOException { synchronized (lock) { ensureOpen(); implFlush(); } }
我们来看看implFlush()方法:
void implFlush() throws IOException { implFlushBuffer(); if (out != null) out.flush(); }
void implFlushBuffer() throws IOException { if (bb.position() > 0) writeBytes(); }
private void writeBytes() throws IOException { bb.flip(); int lim = bb.limit(); int pos = bb.position(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); if (rem > 0) { if (ch != null) { if (ch.write(bb) != rem) assert false : rem; } else { out.write(bb.array(), bb.arrayOffset() + pos, rem); } } bb.clear(); }
当程序执行到out.write(bb.array(), bb.arrayOffset() + pos, rem);这句的时候我不知道是在哪里实现的,断点老是进不去,纠结很久.........
第二天,重新梳理一遍: java.io.FileWriter的构造方法如下:
/** * Constructs a FileWriter object given a File object. * * @param file a File object to write to. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, * or cannot be opened for any other reason */ public FileWriter(File file) throws IOException { super(new FileOutputStream(file)); }
/** * Creates an OutputStreamWriter that uses the default character encoding. * * @param out An OutputStream */ public OutputStreamWriter(OutputStream out) { super(out); try { se = StreamEncoder.forOutputStreamWriter(out, this, (String)null); } catch (UnsupportedEncodingException e) { throw new Error(e); } }
而我上面 用到的out对象是java.io.OutputStream,这里就很清楚了,我用到的肯定是java.io.FileOutputStream对象,那么为什么我断点进入不了呢,后来我把源码重新编译一次放入rt.jar包中,断点进入了 哈哈:
/** * Writes <code>len</code> bytes from the specified byte array * starting at offset <code>off</code> to this file output stream. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. */ public void write(byte b[], int off, int len) throws IOException { writeBytes(b, off, len, append); }
/** * Writes a sub array as a sequence of bytes. * @param b the data to be written * @param off the start offset in the data * @param len the number of bytes that are written * @param append {@code true} to first advance the position to the * end of file * @exception IOException If an I/O error has occurred. */ private native void writeBytes(byte b[], int off, int len, boolean append) throws IOException;
这里最终又用到了本地方法,这时java的任务算是告一段落,剩下的交给操作系统底层来完成了
相关文章推荐
- File I/O source code--读取文件 相关方法阅读
- File I/O source code--新建文件 相关方法阅读
- File I/O source code--Pipe 相关方法阅读
- PHP使用内置函数file_put_contents写入文件及追加内容的方法
- 关于写入文件缓存时报"java.io.FileNotFoundException open failed (is a director)"错误的解决方法
- 写文件 :数组,字典,字符串, NSData 都有同一个 writeToFile 方法写入文件
- 在lnmp服务器用file_put_contents函数写入文件无法写入的解决方法
- PowerShell Out-File向只读文件写入内容的方法
- file()创建文件方法 分类: python python基础学习 2012-12-24 18:17 239人阅读 评论(0) 收藏
- 本方法用于获取指定文件夹的子文件夹中的图片名称,并写入到FileList.ini文件中去(格式...
- PHP使用内置函数file_put_contents写入文件及追加内容的方法
- andorid 解压zip文件、android中文文件存放问题、asset里不能放中文名文件的解决方法、用File读asset的路径的问题、把asset的文件写入机器
- PHP文件写入函数file_put_contents并发追加写入丢失内容问题解决方法
- 在C#.net中做页面上传的程序。用Dhtml的控件:(创建文件上载控件,该控件带有一个文本框和一个浏览按钮。)和类HtmlInputFile的两种方法
- file 读取写入文件 HTML
- 有关AS3跨域读取图片文件报错“checkPolicyFile”的解决方法
- 关于文件操作的若干方法(File类)
- 对ArcEngine中运用到的样式ServerStyle文件进行编辑AddFile和RemoveFile方法出错
- ASP.NET同时上传多个文件,和不使用HTMLFileInput上传的方法(resource about file upload)
- 关于文件流的阅读笔记(文件操作相关总结) [[ 应用过 ]]