第19天-11-IO流(字节流File读写操作)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; /*
字符流
Reader/Writer
FileReader/FileWriter
BufferedReader/BufferedWriter 字节流:
InputStream/OutputStream
FileInputStream/FileOutputStream
需求:想要操作图片数据,这时就要用到字节流
*/
public class FileStream {
public static void main(String[] args) throws IOException {
// writeFile();
readFile_2();
} public static void writeFile() throws IOException {
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("abc厉害".getBytes());
// 写需要close无需flush -- 字符流底层也是一个字节一个字节进行操作,但是需要读取若干个字节,然后查码表输出字符,所以涉及缓存和flush.而字节流就不需要缓存也就无需flush
fos.close();
} public static void readFile_0() throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
// 一个字节一个字节读
int ch;
while ((ch = fis.read()) != -1) {
System.out.println((char) ch);
}
fis.close();
} public static void readFile_1() throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
byte[] buf = new byte[1024];// 1024*N 是字节数组合适的大小
int len;
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len, "utf-8"));
System.out.println(new String(buf, 0, len));
}
fis.close();
} // 字节流特有的available()方法
public static void readFile_2() throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
// int available() 返回下一次对此输入流调用的方法"可以不受阻塞地从'此输入流'读取(或跳过)的估计剩余字节数"(含换行符)
// 如果new一个容量大小恰好为剩余文件字节数的byte[fis.available()],就无需循环而一次读完.但文件体积很大的情况下byte[]申请内存会失败
byte[] buf = new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
}

第19天-12-IO流(拷贝图片)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; /*
拷贝一个图片,思路:
1.用字节读取流对象和源图片关联
2.用字节写入流对象创建一个图片文件,用于存储获取到的图片数据.
3.通过循环读写,完成数据的存储
4.关闭资源
*/
public class CopyPic {
public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fos = new FileOutputStream("2.png");
fis = new FileInputStream("1.png");
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (Exception e) {
throw new RuntimeException("复制文件失败");
} finally {
try {
if (fis != null) fis.close();
} catch (IOException e) {
throw new RuntimeException("读取流关闭失败");
}
try {
if (fos != null) fos.close();
} catch (IOException e) {
throw new RuntimeException("输出流关闭失败");
}
}
}
}

Q:字符流可以用于图片复制吗?

A:不可以,字符流读到的数据,如果在码表里找不到对应的数,则返回一个未知字符对应的数字,未知字符占一个字节。同理,字节流如果错误地截断字符,也会导致乱码。

第19天-13-IO流(字节流的缓冲区)

import java.io.*;

/*
演示mp3的复制(现在都不听mp3了,用图片代替),使用缓冲区.
BufferedInputStream/BufferedOutputStream
*/
public class CopyMp3 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
copy_1();
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
} public static void copy_1() throws IOException {
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("1.png"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("3.png"));
int by;
while ((by = bufis.read()) != -1) {
bufos.write(by);
}
bufis.close();
bufos.close();
}
}

第19天-14-IO流(自定义字节流的缓冲区-read和write的特点)

import java.io.*;

public class MyBufferedInputStream {

    private byte[] buf = new byte[1024];
private int pos, count;
private InputStream in; public MyBufferedInputStream(InputStream in) {
this.in = in;
} // 一次读一个字节,从缓冲区(字节数组)获取
public int myRead() throws IOException {
if (count == 0) { // count == 0表示数组中的元素已经被全部取走,需要再次进行read(buf)
if ((count = in.read(buf)) < 0) return -1;
//通过in对象读取硬盘上的数据,并存储至buf中,count也被重置为数组被填充的长度;如果in.read(buf)返回-1,表示in对象已经读取完毕
pos = 0; // 重置数组指针到0,开始重新读取
byte b = buf[pos];
count--;
pos++;
return b & 0xff; // 读取的类型byte b,返回值向上转换为int b
} else if (count > 0) {
byte b = buf[pos];
count--;
pos++;
return b & 0xff;
}
return -1;
} public void myClose() throws IOException {
in.close();
} public static void copy() throws IOException {
MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("1.png"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("3.png"));
int by;
while ((by = bufis.myRead()) != -1) {
bufos.write(by); // 传入的类型为int,实际上写入的是byte,多余的高位被截去
}
bufos.close();
bufis.myClose();
} public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
copy();
long end = System.currentTimeMillis();
System.out.println(end - start + "ms");
}
}

Q:为什么copy()方法中返回数组元素byte b需要进行 b & 0xff 操作?

A:因为b为byte类型,copy()方法返回值为int类型,问题就是在byte强制类型转换为int过程中发生的。当byte b = buf[pos]返回二进制为1111-1111时,代表的整数值为-1(1的二进制补码等于反码+1,为1111-1111);向上类型转换为int时,就成了4个字节的int值-1(1111-1111-1111-1111-1111-1111-1111-1111)。myReader()方法返回-1表示读取内容完毕,读取就终止了。因此问题变成了:如果正确返回1111-1111,使之不被当作-1?

  11111111 11111111 11111111 11111111  b

&00000000 00000000 00000000 11111111  & 255

---------------------------------------------------

  00000000 00000000 00000000 11111111  --> b & 0xff    (0&0=0;1&0=0;0&1=0;1&1=1,所以 b&255 的低8位是不会变的)

Q:为什么“字节流”读一个字节的方法是int read(),返回类型是int;写一个字节的方法void write(int b),传入类型是int?

A:int read()读取一个字节,返回值被强制向上转换为int;void write(int b)传入一个int值,强制截去高位,只写入低8位(1个字节)

毕向东_Java基础视频教程第19天_IO流(11~14)的更多相关文章

  1. 毕向东_Java基础视频教程第19天_IO流(01~05)

    第19天-01-IO流(BufferedWriter) 字符流的缓冲区 缓冲区的出现提高了对数据的读写效率. 对应类缓冲区要结合流才可以使用. BufferedWriter BufferedReade ...

  2. 毕向东_Java基础视频教程第19天_IO流(06~10)

    第19天-06-IO流(装饰设计模式) 装饰设计模式: 当想要对已有的对象进行功能增强时, 可以定义类,将已有对象传入,基于已有的功能,并提供加强功能.那么这个自定义的类称为装饰类. 装饰类通常会通过 ...

  3. 毕向东_Java基础视频教程第19天_IO流(20~22)

    第19天-20-IO流(改变标准输入输出设备) static void setIn(InputStream in) Reassigns the "standard" input s ...

  4. 毕向东_Java基础视频教程第19天_IO流(18~19)

    第19天-18-IO流(流操作规律 - 1) 通过三个步骤来明确"流操作"的规律: 明确数据流的"源和目的" 源, 输入流: InputStream/Reade ...

  5. 毕向东_Java基础视频教程第19天_IO流(15~17)

    第19天-15-IO流(读取键盘录入) InputStreamReader是字节流通向字符流的桥梁,它使用指定的charset读取字节并将其解码为字符.它使用的字符集可以由名称指定或显式给定,或者可以 ...

  6. 毕向东_Java基础视频教程第20天_IO流(7~10)

    第20天-07-IO流(递归) package bxd; import java.io.File; public class FileDemo3 { // 非递归打印 public static vo ...

  7. 毕向东_Java基础视频教程第21天_IO流(1)

    第21天-01-IO流(对象的序列化) ObjectInputStream与ObjectOutputStream 被操作的对象需要实现Serializable接口(标记接口) 非必须, 但强烈建议所有 ...

  8. 毕向东_Java基础视频教程第20天_IO流(15~17)

    第20天-15-IO流(打印输出流) 打印输出流:PrintWriter与PrintStream 两者的区别:Since JDK 1.4 it's possible to specify the ch ...

  9. 毕向东_Java基础视频教程第20天_IO流(11~14)

    第20天-11-IO流(Properties简述) .properties是一种主要在Java相关技术中用来存储应用程序的可配置参数的文件的文件扩展名.它们也可以存储用于国际化和本地化的字符串,这种文 ...

随机推荐

  1. Wijmo 5 + Ionic Framework之:费用跟踪 App

    Wijmo 5 + Ionic Framework之:费用跟踪 App 费用跟踪应用采用了Wijmo5和Ionic Framework创建,目的是构建一个hybird app. 我们基于<Mob ...

  2. FineUI开发实践

    ASP.NET-FineUI开发实践-7 摘要: 下拉显示grid列表.其实很简单,但是试了很多方法,水平有限,主要是都不好使,还是简单的好使了,分享下.先是看了看网上的,是直接写个了extjs控件类 ...

  3. 算法回顾--N皇后问题简单回顾

    前言 最近学习的过程中,不知道哪门子的思维发散,突然又遇见皇后问题了,于是乎老调重弹,心里琢磨,虽然思路大家都容易懂,哪怕是最简单的野蛮回溯法,说着简单,但是如果非得编码实现?我可以一次性写出来OK的 ...

  4. ThoughtWorks Merchant's Guide To The Galaxy

    ThoughtWorks笔试题之Merchant's Guide To The Galaxy解析 一.背景 在某网站上看到ThoughtWorks在武汉招人,待遇在本地还算不错,就投递了简历.第二天H ...

  5. 基于.NET的微信SDK

    超级懒汉编写的基于.NET的微信SDK   一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发“框架”,但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的 ...

  6. 在现有代码中通过async/await实现并行

    在现有代码中通过async/await实现并行 一项新技术或者一个新特性,只有你用它解决实际问题后,才能真正体会到它的魅力,真正理解它.也期待大家能够多分享解一些解决实际问题的内容. 在我们遭遇“黑色 ...

  7. 转载Mvc的多层架构

    Mvc的多层架构 分享一个Mvc的多层架构,欢迎大家拍砖斧正   多层架构是什么? 多层架构是开发人员在开发过程当中面对复杂且易变的需求采取的一种以隔离控制为主的应对策略,关于多层架构的标准,我认为有 ...

  8. iOS推送服务细节回顾

    iOS推送服务细节回顾 之前在做推送功能时候,就总结过一系列证书的制作,OC代码实现和服务器搭建等经验.又过了一段时间了,前前后后对推送服务做了多次的完善和优化,有iOS客户端的,还有本地服务器端的. ...

  9. 2014.first[未填]

    之后就按照自己的直觉,整理了第一套,难度为简单,差不多比2013noipday1水一点...先练练手而已 T1 vijos1196吃糖果游戏 博弈论 依题意,我们可知,如果去分数目为2,3,7,8必输 ...

  10. win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)

    使用overlapped I/O并搭配event对象-----win32多线程-异步(asynchronous) I/O事例,会产生两个基础性问题. 第一个问题是,使用WaitForMultipleO ...