创建内存中的FileDescriptor

时间:2017-10-24 18:23:03

标签: java android file-descriptor bytearrayoutputstream bytearrayinputstream

Android中的

FileDescriptor API说:

  

文件描述符类的实例用作不透明句柄   表示打开文件的底层机器特定结构,   打开的套接字,或其他字节源或接收器。

我想使用ByteArrayOutputStreamByteArrayInputStream

创建一个FileDescriptor对象

此外,FileDescriptor是最终类,无法覆盖。它唯一的构造函数 -

  

构造(无效) FileDescriptor对象。

知道如何在Android中使用FileDescriptor吗?

修改

我想在MediaMuxer中使用它。我希望将媒体数据保存在内存中,并将其复制到TCP套接字以进行实时流式传输,而不是写入文件。所以我的FileDescriptor应该是“字节汇集”。

2 个答案:

答案 0 :(得分:0)

您可以将System.out重定向到ByteArrayOutputStream 并使用FileDescriptor.out作为filedescriptor

ByteArrayOutputStream buff = new ByteArrayOutputStream();
PrintStream old = System.out;
System.setOut(new PrintStream(buff));

... use FileDescriptor.out ...

System.setOut(old);
System.out.println(new String(buff.toByteArray()));

答案 1 :(得分:0)

使用LocalSocket,但要小心,因为会带来安全隐患。

LocalSocket是用于Unix域套接字的Android API。域套接字与TCP / IP套接字类似,不同之处在于它们仅存在于设备上,不能用于通过网络的通信。

一种简单但不安全的解决方案如下:

// Create a unique name for the socket.
String name = "your.package.name-" + UUID.randomUUID();

// Bind a server to the socket.
final LocalServerSocket server = new LocalServerSocket(name);

// Connect a client to the socket.
LocalSocket client = new LocalSocket(LocalSocket.SOCKET_STREAM);
client.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));

// Start a thread to read from the server socket.
new Thread(new Runnable {
    @Override
    public void run() {
        LocalSocket socket = server.accept();

        // To read data sent by the client, read from socket.getInputStream().
        // To send data to the client, write to socket.getOutputStream().

        // After you are done you will need to call socket.close().
    }
}).start();

// Get the FileDescriptor associated with the client.
// You can use this FileDescriptor to write data to and/or read data
// sent from the server.
FileDescriptor fileDescriptor = client.getFileDescriptor();

// After you are done you will need to call server.close() and client.close().

这将在抽象套接字名称空间中创建一个套接字。这是不安全的,因为域套接字是系统范围的,并且抽象名称空间中的套接字不受任何权限系统的限制。连接或绑定到抽象命名空间中的名称的唯一要求是知道名称,并且攻击者可以通过反编译轻松发现应用程序使用的套接字名称。另外,另一个应用可能会偶然使用相同的套接字名称。因此,另一个应用程序可能会拦截您的数据,或通过套接字发送意外的数据,因此很难防范。

一种更好但更复杂的解决方案是在文件系统名称空间中创建一个套接字。用于执行此操作的API非常奇怪,但是可以通过以下方式实现:

// Create a unique name for the socket in your app's private data area.
// Note this example creates a file named like socket-xxxx in the root of
// your app's private data area. You might want to put it in a subdirectory.
String name = context
    .getFileStreamPath("socket-" + UUID.randomUUID())
    .getAbsolutePath();
LocalSocketAddress address = new LocalSocketAddress(name, LocalSocketAddress.Namespace.FILESYSTEM);

// Bind a server to the socket.
LocalSocket server = new LocalSocket(LocalSocket.SOCKET_STREAM);
server.bind(address);
final LocalServerSocket serverWrapper = new LocalServerSocket(server.getFileDescriptor());

// Connect a client to the socket.
LocalSocket client = new LocalSocket(LocalSocket.SOCKET_STREAM);
client.connect(address);

// Start a thread to read from the server socket.
new Thread(new Runnable {
    @Override
    public void run() {
        LocalSocket socket = serverWrapper.accept();

        // To read data sent by the client, read from socket.getInputStream().
        // To send data to the client, write to socket.getOutputStream().

        // After you are done you will need to call socket.close() and
        // serverWrapper.close().
    }
}).start();

// Get the FileDescriptor associated with the client.
// You can use this FileDescriptor to write data to and/or read data
// sent from the server.
FileDescriptor fileDescriptor = client.getFileDescriptor();

// After you are done you will need to call server.close() and client.close().

这确实在文件系统上创建了一个文件,但是任何通过套接字的数据都不会写入磁盘,它完全在内存中。该文件只是代表套接字的名称,类似于/dev中代表设备的文件。由于套接字是通过文件系统访问的,因此必须遵守通常的文件系统权限,因此可以通过将套接字放置在应用程序的私有数据区域中来限制对套接字的访问。

由于此技术会在文件系统上创建文件,因此最好在完成后删除该文件,并且还可能经常检查和清理旧的套接字,以防应用程序崩溃和崩溃。留下旧文件。