java - 为什么 JavaFX Image 不直接从 FileInputStream 读取文件本身?

标签 java image javafx filenotfoundexception fileinputstream

我正在编写一个交易程序,允许用户上传自己的图片,供其他客户在查看他们发布的列表时查看。请求时从服务器发送图像文件(.png 或 .jpeg 文件)。

似乎当使用 FileInputStream 作为新图像的参数时,尝试打开图像的客户端正在他们自己的计算机上查找该文件(检查它自己的文件系统),而不是直接读取图像文件本身已从服务器发送给它。

在我发布的示例中,我们假设它在 IDE 中运行,而不是作为 JAR。发送文件的服务器程序能够从其“src”目录成功访问“avatar.png”。

我在下面构建了一个最小的可执行示例,由服务器和客户端组成,以表示手头的实际问题。服务器和客户端示例在本地网络上的不同计算机上运行。该示例重现了该问题。

来自 FileInputStream 文档:

FileInputStream is meant for reading streams of raw bytes such as image data.

该示例抛出以下异常:

java.io.FileNotFoundException: avatar.png (No such file or directory)

这表明客户端正在其自己的文件系统中查找“avatar.png”。

例如服务器:

public class ImageTesterServer {

public static void main(String[] args) {

    ImageTesterServer server = new ImageTesterServer();
    server.sendImage();

}


private void sendImage()
{
    ServerSocket server = null;
    Socket client = null;

    try {
        // Accept client connection, create new File from the 'avatar.png' image, and send to client
        server = new ServerSocket();
        System.out.println("Awaiting client connection...");

        client = server.accept();
        System.out.println("Client connected.");

        File imageFile = new File("avatar.png");
        ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
        oos.writeObject(imageFile);

        System.out.println("Sent image file.");

    } catch (IOException e) {
        e.printStackTrace();
    }
    finally {  // Close sockets
        try {
            if (client != null)
                client.close();
            if (server != null)
                server.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

}

客户端:

public class ImageTesterClient extends Application {

public static void main(String[] args)
{
    Application.launch(args);
}

@Override
public void start(Stage primaryStage)
{
    ImageTesterClient client = new ImageTesterClient();
    Image avatar = client.getServerFile();   // Retrieve the image's file from the server
    ImageView picture = new ImageView(avatar);

    StackPane root = new StackPane();
    root.getChildren().add(picture);

    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.show();
}

private Image getServerFile()
{
    Socket socket = null;
    ObjectInputStream ois;

    try {

        socket = new Socket("192.168.1.147", 5000);   // Open new socket connection to server on another local network computer
        ois = new ObjectInputStream(socket.getInputStream());
        File imageFile = (File)ois.readObject();
        Image avatar = new Image(new FileInputStream(imageFile));
        return avatar;

    } catch (IOException | ClassNotFoundException ex) {
        ex.printStackTrace();
    }
    finally {  // Close the socket if not null
        try {
            if (socket != null)
                socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    return null;
}

}

如何强制客户端图像使用从服务器接收到的文件 (avatar.png) 本身,而不是尝试查看自己的文件系统?

最佳答案

File 类不表示文件的内容。它只是文件路径的表示。这种混淆是 File 类被认为已过时(尽管未弃用)并已被 Path 取代的众多原因之一。类。

因此,当您执行 oos.writeObject(imageFile); 时,您发送的不是文件的内容,而是该文件的路径。显然,一台计算机上存在文件路径并不能保证同一路径在另一台计算机上有效。

您必须单独发送文件的内容。一种方法是打开 FileInputStream,将其包装在 BufferedInputStream 中,然后使用 BufferInputStream 的 transferTo。方法:

oos.writeObject(imageFile);
try (InputStream stream =
    new BufferedInputStream(new FileInputStream(imageFile))) {

    stream.transferTo(oos);
}

并且在客户端,使用文件的长度来确定读取多少字节:

File imageFile = (File) ois.readObject();
long length = imageFile.length();

Path imagePath = Files.createTempFile(null, imageFile.getName());
try (FileChannel imageChannel = FileChannel.open(imagePath, 
    StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {

    imageChannel.transferFrom(Channels.newChannel(ois), 0, length);
}

Image avatar = new Image(imagePath.toUri().toString());

关于java - 为什么 JavaFX Image 不直接从 FileInputStream 读取文件本身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51699820/

相关文章:

java - 使用 selenium webdriver 下载图像

java - 如何在 SWT 小部件旁边显示错误标记?

python - 更新 JPEG 文件中的 JFIF 缩略图

python - 在 RGB 图像的 tensorflow 中使用 SSIM 损失函数

java - getClass().getResource() 加载文件失败,File() 有效

java - 文件保存 500 个从 0 到 1000 的随机数。将这些数字写入文件,然后打开文件并一一读取数字

使用套接字上传Java文件,需要上传文件的百分比?

javascript - 传单:在初始 View 上移动 map

java - 使用线程在 JavaFX 中移动矩形

java - 获取加密文件的文件名