本人开发android app 通过wifi与硬件设备进行连接,类似物联网项目。通讯协议使用的是与硬件共同制定的。硬件设备使用C语言,android 我这边使用的是java。(没有服务器,也不想用服务器!)
目前遇到的问题:
部分代码如下:
while (true) {
if (wCmdId == enNetCmd.CMD_PostDownloadFileData) {
PictureData = new byte[wSize - 89];
len = inputStream.read(PictureData);
try {
FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/ftp" + FileName, true);
fos.write(PictureData, 0, len);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.如果实现的方式不对,请问使用什么方式去传输图片数据?请详细地说明解决问题的方法以及实现的方式。
你的可能没有读全,对结果len判断一下,没读全继续读
你打印一下那个len的大小,看看是否和图片大小一样,如果一样考虑写入文件问题,不一样考虑网络传输问题
你尝试下面2个方法,试试吧,如果有帮助,解决的话请采纳
方法一:
//初始化streams
final FileOutputStream fileOutputStream = new FileOutputStream(toWriteTo + url.getPath().replaceAll(".*/", ""));
final InputStream inputStream = socket.getInputStream();
// Header end flag
boolean headerEnded = false;
byte[] bytes = new byte[2048];
int length;
while ((length = inputStream.read(bytes)) != -1) {
// 如果已经到达标头的末尾,则照常将字节写入文件。
if (headerEnded)
fileOutputStream.write(bytes, 0, length);
// 通过比较当前字节和接下来的 3 个字节来定位标头的末尾,
// HTTP 标头结尾为“\r\n\r\n”(整数表示形式为 13 10 13 10),
// 如果到达头部末尾,则将标志设置为 true,
// 并将当前缓冲的字节数组中的剩余数据写入文件。
else {
for (int i = 0; i < 2048; i++) {
if (bytes[i] == 13 && bytes[i + 1] == 10 && bytes[i + 2] == 13 && bytes[i + 3] == 10) {
headerEnded = true;
fileOutputStream.write(bytes, i+4, 2048-i-4);
break;
}
}
}
}
inputStream.close();
fileOutputStream.close();
方法二:
你可以参考Netty附带的实现,您可以按如下方式实现它:ChunkedInput<ByteBuf>
public class ChunkedList implements ChunkedInput<ByteBuf> {
private static final byte[] EMPTY = new byte[0];
private byte[] previousPart = EMPTY;
private final int chunkSize;
private final Iterator<Object> iterator;
public ChunkedList(int chunkSize, List<Object> objs) {
this.chunkSize = chunkSize;
this.iterator = objs.iterator();
}
public ByteBuf readChunk(ChannelHandlerContext ctx) {
return readChunk(ctx.alloc());
}
public ByteBuf readChunk(ByteBufAllocator allocator) {
if (isEndOfInput())
return null;
else {
ByteBuf buf = allocator.buffer(chunkSize);
boolean release = true;
try {
int bytesRead = 0;
if (previousPart.length > 0) {
if (previousPart.length > chunkSize) {
throw new IllegalStateException();
}
bytesRead += previousPart.length;
buf.writeBytes(previousPart);
}
boolean done = false;
while (!done) {
if (!iterator.hasNext()) {
done = true;
previousPart = EMPTY;
} else {
Object o = iterator.next();
byte[] bytes = o instanceof String ? ((String) o).getBytes() : (byte[]) o;
bytesRead += bytes.length;
if (bytesRead > chunkSize) {
done = true;
previousPart = bytes;
} else {
buf.writeBytes(bytes);
}
}
}
release = false;
} finally {
if (release)
buf.release();
}
return buf;
}
}
public long length() {
return -1;
}
public boolean isEndOfInput() {
return !iterator.hasNext() && previousPart.length == 0;
}
public long progress() {
return 0;
}
public void close(){
//close
}
}
你的这一行代码不是获取全部的流数据,len = inputStream.read(PictureData);,并且也没有对输入流关流的操作。
byte[] bytes = new byte[2048];
int len = -1;
Log.d(Constants.TAG, " writeToFile 3");
while ((len = inputStream.read(bytes)) != -1) {
// Log.d(Constants.TAG, Arrays.toString(bytes));
randomFile.write(bytes, 0, len);
}
通过 socket 通讯读取 inputStream 到 byte[] 数组不会改变图片数据本身。inputStream 和 byte[] 都是用来存储数据的容器,从 inputStream 读取数据到 byte[] 数组只是在两个容器之间进行数据的复制。这并不会改变图片数据本身。
但是,在进行数据读取和复制的过程中,如果出现了异常或者数据丢失,可能会导致图片显示异常。因此,在进行数据读取和复制的过程中,应该注意检查异常并确保数据的完整性。
例如,在读取数据时,可以使用 try-catch 语句来捕获异常,并进行相应的处理;在复制数据时,可以使用一些校验和算法来确保数据的完整性。
如果图片显示异常,可能是因为在处理图片数据时出现了问题,例如图片格式不正确、图片数据损坏或丢失等。可以尝试检查代码,确保在处理图片数据时的正确性。
通过测试,一般情况下接收2048字节,但是有的时候会接收1359字节,判断一下长度,将不够的继续inputStream.read(),然后将数据拼接。