今天需要利用百度的图片识别来获取图片中的问题, 百度的api要求把图片用Base64编码以后, 再用encodeURI编码后发送图片数据.
既然需要从把图片用Base64编码, 就需要知道图片的大小, 然后new一个对应大小的数据 . 当然,new一个比较大的字节数组 ,或者把每次读到的字节累加起来也可以. 但是顺便了解一下如何获取文件的大小, 也挺有意思的.
网上查阅发现有人用FileInputStream的available()方法 . 查阅官方的api是这样说的:
有点不好理解 . 通过stackoverflow查阅得知 :
available()方法的本来用途是查看缓存区中时候还有可用数据:
本地文件 :
读取本地文件时, FileInputSteam的available()方法被重写了 , 所以并不是把本地文件读到缓存里以后才返回大小 ,
实际是根据本地文件的描述信息 , 返回的文件的大小.
关键是:fileSystem.ioctlAvailable(fd.descriptor);
调用了FileSystem这是java没有公开的一个类,JavaDoc API没有。
其中fileSystem 是一个IFileSystem对象,IFileSySTEM是java没有公开的一个类,JavaDoc API中没有;
fd是一个FileDescriptor对象,即文件描述符
网络文件 :
如果想要获得网络文件的大小 , 用available()方法可能得不到正确的大小, 因为网络获得的流, read()会发生堵塞, 文件过大, 也要分批次发送 . 还有很容易得到0 , 因为网络的数据可能还没有到达,就调用了available()方法.
和本地文件类似, 想要获得文件大小, 也可以用对文件的"描述" , 就是在response中Content-length的信息.
在URLConnection类中有getContentLength()方法, 就是获取文件大小.
当然使用HttpURLConnection中的getHeaderFields(String name)也是一样的.
也是一样的.
/**
* Returns the value of the {@code content-length} header field.
* <P>
* <B>Note</B>: {@link #getContentLengthLong() getContentLengthLong()}
* should be preferred over this method, since it returns a {@code long}
* instead and is therefore more portable.</P>
*
* @return the content length of the resource that this connection's URL
* references, {@code -1} if the content length is not known,
* or if the content length is greater than Integer.MAX_VALUE.
*/
public int getContentLength() {
long l = getContentLengthLong();
if (l > Integer.MAX_VALUE)
return -1;
return (int) l;
}
参考:http://hold-on.iteye.com/blog/1017449
https://stackoverflow.com/questions/3843363/thread-interrupt-not-ending-blocking-call-on-input-stream-read
https://zhidao.baidu.com/question/455816162.html