【面试官】那Java字节流和字符流有什么区别?

  • 面试官:你说下对Java IO的理解?
  • 面试官:那要怎么读取字节流?
  • 面试官:你说的这些不是实例,我要的是能真正读取的?
  • 面试官:为什么加一层缓存流就能提高读取效率?
  • 面试官:那字符流读取呢?
  • 面试官:输出流你也讲一讲?
  • 面试官:那字节流和字符流有什么区别?

大家好,我是南哥。

一个Java学习与进阶的领路人,相信对你通关面试进入心心念念的公司有所帮助。

文章目录

  1. JavaI/O的理解
  2. 输入流
    1. 字节输入流抽象基类
    2. 字节输入流读取
    3. 提高读取效率
    4. 字符输入流
  3. 输出流
    1. 输出流
  4. 字节流和字符流区别

1. Java I/O的理解

面试官:你说下对Java IO的理解?

Java I/O有两个参与对象,一个是I/O源端,一个是想要和I/O源端通信的各种接收端,比如程序控制IDEA控制台输出、读取文件A写入文件B等,我们程序要保证的就是IO流的顺利读取和顺利写入。JDK把对Java IO的支持都放在了package java.io包下,南哥数了数,一个有86个类和接口。

我们看下package java.io包最常用的Reader和Writer接口,他们的作者都是Mark Reinhold。这位老哥是谁?是Oracle Java平台组的首席架构师,也是字符流读取器和写入器的首席工程师。这么有来头,看来Java I/O的程序设计不简单,我们可以从中学到不少好用的东西。

/** 
 * @author      Mark Reinhold
 * @since       JDK1.1
 */
public abstract class Reader implements Readable, Closeable { }
public abstract class Writer implements Appendable, Closeable, Flushable { }

2. 输入流

2.1 字节输入流抽象基类

面试官:那要怎么读取字节流?

我们先讲输入流,后面再讲下输出流。输入流又分为字节流和字符流,顾名思义,字节流按字节来读取,操作的数据单元是8位的字节;而字符流按字符来读取,操作的数据单元是16位的字符。

读取字节的抽象基类是InputStream,这个基类提供了3个方法给我们来读取字节流。

(1)从输入流读取下一个数据字节,值字节以0到255范围内的int返回。

public abstract int read() throws IOException

(2)从输入流读取一定数量的字节并将它们存储到缓冲区数组b中。

public int read(byte b[]) throws IOException

(3)从输入流读取最多len个字节的数据到字节数组中。

public int read(byte b[], int off, int len) throws IOException

大家注意以上方法的返回参数都是int类型,当正常读取时,int返回的是读取的字节个数;而当int返回-1,就表明输入流到达了末尾。

2.2 字节输入流读取

面试官:你说的这些不是实例,我要的是能真正读取的?

上文的是抽象的接口,本身并不具备实际的功能。真正能够读取文件的是InputStream抽象基类的子类实现,例如文件流FileInputStream,有了他,我们读取音频、视频、gif等等都不是问题。

// 文件流读取文件
FileInputStream stream = new FileInputStream(SOURCE_PATH);

我们还可以在外面加一层缓存字节流来提高读取效率,在外层套上BufferedInputStream对象,为什么可以提高读取效率我下文会讲到。

BufferedInputStream stream = new BufferedInputStream(new FileInputStream(SOURCE_PATH));

以上通过字节流我们是以n个字节来读取的,如果要用readLine()读取某一行这种场景下就不适用了。我们可以把缓存字节流换成缓存字符流来承接,使用InputStreamReader转换流把字节输入流转换成字符输入流。

如下代码所示。

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(SOURCE_PATH)));

2.3 提高读取效率

面试官:为什么加一层缓存流就能提高读取效率?

为什么加一层缓存

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试突击 文章被收录于专栏

👉以面试官面试的形式,涵盖了你怒怼大厂面试官、拿下大厂面试所需掌握的核心知识、面试重点! 👉相信一定对你顺利通关面试、拿到理想Offer有所帮助! 👉花费大量精力去制作本专栏,创作不易,各位的支持就是我创作的最大动力!

全部评论
牛啊
1 回复 分享
发布于 08-02 15:37 广东

相关推荐

这里我总结一下我的嵌入式的八股文积累,体量比较大,基本都是我秋招面试来遇到的面试真题,什么题都有主要是偏C/C++嵌入式这一块,希望能帮到各位小伙伴和后来的人,希望大家送送花点点赞这个系列大概分为好几期吧,尽快肝出来,大家只要面试前抽个一个小时每次背背,基本上八股部分不会有太大问题我都放在我主页置顶希望小伙伴们捧捧场千万别只点收藏哦urat:两根线 无时钟 异步 全双工i2c:两根线 时钟和数据 同步 半双工 可以多主机多从机传输速率100K,400K和3.4M三种速率(bps) SCL和SDA:SCL高电平期间SDA有高变低为起始信号;SCL高电平期间SDA由低变高为终止信号;SCL高电平期间SDC低位0,高为1;iic采用7bit寻址字节,1-7表示从机地址,0位表示传输方向;表示读写每一个字节必须保证是8bit长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随1bit的应答位,每一帧数据有九位通行流程:1. 启动信号:主设备发送起始信号,通过拉低SDA线,同时SCL线保持高电平。2. 地址发送:主设备发送目标从设备的地址及读/写位。地址后,目标从设备应应答。3. 数据传输:主设备或从设备根据读/写位进行数据传输。每传输一字节后,接收方应发应答位。4. 停止信号:完成数据传输后,主设备发送停止信号,释放SDA线,SCL线保持高电平。- ACK:表示“我已收到,继续发送”。- NACK:表示“我未收到或我已完成,不要再发送了”。spi:四线制或者三线制 时钟 、ss、miso、mosi同步 全双工 有发必有会回 spi传输速率 :可以达到50Mbps一主多从计算数组长度:通过sizeof(),数组长度除以数组第一个元素的长度c通过strlen()函数, c++通过.size()数组和链表的区别:数组和链表是两种不同的**数据存储**方式数组是一组具有相同数据类型的变量集合链表是一个中物理存储单元上不连续的存储结构,各个元素的逻辑顺序通过链表中的指针链接实现数组:(1)数组在内存中连续; (2)使用数组之前,必须事先固定数组长度,不支持动态改变数组大小;(3) 数组元素增加时,有可能会数组越界;(4) 数组元素减少时,会造成内存浪费;(5)数组增删时需要移动其它元素。数组从栈上分配内存,使用方便,但是自由度小。数组在内存中顺序存储,可通过下标访问,访问效率高。数组的大小是固定的,所以存在访问越界的风险。数组的存储空间是栈上分配的,存储密度大,当要求存储的大小变化不大时,且可以事先确定大小,宜采用数组存储数据。数组的存储空间是栈上分配的,存储密度大,当要求存储的大小变化不大时,且可以事先确定大小,宜采用数组存储数据。链表:(1)链表采用动态内存分配的方式,在内存中不连续 (2)支持动态增加或者删除元素 (3)需要时可以使用malloc或者new来申请内存,不用时使用free或者delete来释放内存。链表从堆上分配内存,自由度大,但是要注意内存泄漏。链表从堆上分配内存,自由度大,但是要注意内存泄漏。链表访问效率低,如果想要访问某个元素,需要从头遍历。只要可以申请得到链表空间,链表就无越界风险。链表的存储空间是堆上动态申请的,当要求存储的长度变化较大时,且事先无法估量数据规模,宜采用链表存储。链表插入、删除效率高,当线性表要求频繁插入和删除时,宜采用链表结构。vector和list的区别+应用:Vector:连续存储的容器,动态数组,在堆上分配空间底层实现:数组性能:适用场景:经常随机访问,且不经常对非尾节点进行插入删除,因为尾节点插入涉及空间问题List:动态链表,在堆上分配空间,每插入一个元数都会分配空间,每删除一个元素都会释放空间。底层:双向链表性能:访问:随机访问性能很差,只能快速访问头尾节点插入:很快删除:很快vector拥有一段连续的内存空间,因此支持随机访问,如果需要高效的随即访问,而不在乎插入和删除的效率,使用vector。list拥有一段不连续的内存空间,如果需要高效的插入和删除,而不关心随机访问,则应使用list。进程和线程的区别:进程:一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段也因为进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响线程:进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以(IPC)进行。线程只是一个进程中的不同执行路径。一个线程死掉就等于整个进程死掉。在通信机制上:进程的通信机制**相对很复杂,譬如管道,信号,消息队列,共享内存,套接字等通信机制,而线程由于共享数据段所以通信机制很方便线程通信主要可以分为三种方式,分别为共享内存、消息传递和管道流1.管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。(同步互斥机制)2.命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据:管道一端的进程顺序地将进程数据写入缓冲区,另一端的进程则顺序地读取数据,该缓冲区可以看做一个循环队列3.消息队列MessageQueue:消息队列就是一个消息的链表,是一系列保存在内核中消息的列表。用户进程可以向消息队列添加消息,也可以向消息队列读取消息。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。4.共享内存SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,共享内存允许两个或多个进程共享一个给定的存储区。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。5.信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。6.套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。基于网路型,基于文件型7.信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
点赞 评论 收藏
分享
9.25boss上投递,由于国庆节导致面试时间拉的较长,三面全是技术面,面的头都快要蒙掉了。9.29一面面试官很年轻,对我的竞赛很感兴趣,问了大概有半个小时,用到了什么方法,算法的原理,怎么实现的,都是自己全程参与的比赛,答得还可以。然后开始问项目,k8s的架构和相关组件的作用、docker的打包部署原理、docker是怎么实现隔离的。常规八股,输入url到网页显示的整个流程、进程线程协程的区别、tcp和udp的不同。手撕:一个数字数组有一个错误的数字重复了,找出来它的位置和并输出正确的数。10.11二面面试官也很年轻,先问项目的具体细节。八股:调度算法、线程的几种状态以及转换条件、dns的具体流程、ARP协议的作用、timewait的作用、对称加密和非对称加密、什么是证书(这个面试官比较喜欢深挖,然后一直问到我答不出来)手撕:简单题:他自己出的题目,一个文件有一百行数据,请读出并记录重复行的行数(hashmap实现)10.14三面一位年龄较大的leader,人很不错,一直在引导我回答,还给我提了建议(应该怎么清楚的回答问题、学技术多去理解原理),学到很多。挑一个感觉比较好的项目讲一讲,然后问项目的细节。k8s中pod的生命周期、什么是微服务八股:输入url到网页显示的整个流程、dns返回ip的名称(没想起来,反向dns)、http和https有什么不同、四次挥手的过程、为什么一定要是四次而不会是三次和五次介绍了下我的论文,对我的论文比较感兴趣,聊了十多分钟。无手撕反问:对年轻人的未来发展有什么建议、简历还有什么需要补充的(说简历只是个敲门砖)、后续的流程(有hr打电话就是通过了,没打电话就G了)找个日常实习真难,让本来就少的头发又掉不少,许愿一个oc
点赞 评论 收藏
分享
3 4 评论
分享
牛客网
牛客企业服务