Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过Windows远程桌面(tsclient)写入时,Java会创建巨大的文件_Java_Windows_File Io_Remote Desktop - Fatal编程技术网

通过Windows远程桌面(tsclient)写入时,Java会创建巨大的文件

通过Windows远程桌面(tsclient)写入时,Java会创建巨大的文件,java,windows,file-io,remote-desktop,Java,Windows,File Io,Remote Desktop,当我们的Swing应用程序通过Windows远程桌面(应用程序托管在用户连接的终端服务器上)向用户本地计算机写入文件时,我们的一个客户端报告了一个非常奇怪的问题 流程是: 用户通过远程桌面登录并运行应用程序(其C:\包含在“本地资源”中) 在工作时,他们将数据从数据库导出到文件中 用户选择要导出的数据 用户在本地计算机上选择目标文件,如\\tsclient\C\Temp\TestFile.txt 文件可能很大,所以每批从数据库中提取1000行并写入文件 在第二批中,当Java打开文件并再次写入

当我们的Swing应用程序通过Windows远程桌面(应用程序托管在用户连接的终端服务器上)向用户本地计算机写入文件时,我们的一个客户端报告了一个非常奇怪的问题

流程是:

  • 用户通过远程桌面登录并运行应用程序(其
    C:\
    包含在“本地资源”中)
  • 在工作时,他们将数据从数据库导出到文件中
  • 用户选择要导出的数据
  • 用户在本地计算机上选择目标文件,如
    \\tsclient\C\Temp\TestFile.txt
  • 文件可能很大,所以每批从数据库中提取1000行并写入文件
  • 在第二批中,当Java打开文件并再次写入时,一些非常奇怪的事情开始发生了!
    • 该文件的大小迅速增加,并在2GB左右停止
    • 然后数据继续写入文件
我不确定这是核心Java库、远程桌面实现还是两者结合的问题。我们的应用程序也是通过Citrix托管的,Citrix运行良好,写入本地磁盘或UNC网络路径也运行良好

我创建了一个演示该问题的程序,连接到带有远程桌面的计算机(确保
C:\
是“本地资源”),然后运行该程序以查看一些非常奇怪的行为!我使用的是JDK-7u45

import static java.nio.file.StandardOpenOption.APPEND;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.util.Collections;

/**
 * Demonstrates weird issue when writing (appending) to a file over TsClient (Microsoft Remote Desktop).
 * 
 * @author Martin
 */
public class WriteOverTsClientDemo
{
    private static final File FILE_TO_WRITE = new File("\\\\tsclient\\C\\Temp\\TestFile.txt");
    //private static final File FILE_TO_WRITE = new File("C:\\Temp\\TestFile.txt");

    private static final String ROW_DATA = "111111111122222222223333333333444444444555555555566666666667777777777888888888899999999990000000000";

    public static void main(String[] args) throws IOException
    {
        if (!FILE_TO_WRITE.getParentFile().exists())
        {
            throw new RuntimeException("\nPlease create directory C:\\Temp\\ on your local machine and run this application via RemoteDesktop with C:\\ as a 'Local resource'.");
        }
        FILE_TO_WRITE.delete();
        new WriteOverTsClientDemo().execute();
    }

    private void execute() throws IOException
    {
        System.out.println("Writing to file: " + FILE_TO_WRITE);
        System.out.println();

        for (int i = 1; i <= 10; i++)
        {
            System.out.println("Writing batch " + i + "...");
            writeDataToFile(i);
            System.out.println("Size of file after batch " + i + ": " + FILE_TO_WRITE.length());
            System.out.println();
        }
        System.out.println("Done!");
    }

    private void writeDataToFile(int batch) throws IOException
    {
        Charset charset = Charset.forName("UTF-8");
        CharsetEncoder encoder = charset.newEncoder();

        try(OutputStream out = Files.newOutputStream(FILE_TO_WRITE.toPath(), CREATE, WRITE, getTruncateOrAppendOption(batch));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder)))
        {
            writeData(batch, writer);
        }
    }

    private void writeData(int batch, BufferedWriter writer) throws IOException
    {
        for (String data : createData())
        {
            writer.append(Integer.toString(batch));
            writer.append(" ");
            writer.append(data);
            writer.append("\n");
        }
    }

    private Iterable<String> createData()
    {
        return Collections.nCopies(100, ROW_DATA);
    }

    /**
     * @return option to write from the beginning or from the end of the file
     */
    private OpenOption getTruncateOrAppendOption(int batch)
    {
        return batch == 1 ? TRUNCATE_EXISTING : APPEND;
    }
}
导入静态java.nio.file.StandardOpenOption.APPEND;
导入静态java.nio.file.StandardOpenOption.CREATE;
导入静态java.nio.file.StandardOpenOption.TRUNCATE_;
导入静态java.nio.file.StandardOpenOption.WRITE;
导入java.io.BufferedWriter;
导入java.io.File;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.io.OutputStreamWriter;
导入java.nio.charset.charset;
导入java.nio.charset.CharsetEncoder;
导入java.nio.file.Files;
导入java.nio.file.OpenOption;
导入java.util.Collections;
/**
*演示通过TsClient(Microsoft远程桌面)写入(附加)文件时出现的奇怪问题。
* 
*@作者马丁
*/
公共类WriteOverTsClientDemo
{
私有静态最终文件File TO WRITE=新文件(\\\\tsclient\\C\\Temp\\TestFile.txt);
//私有静态最终文件File_TO_WRITE=新文件(“C:\\Temp\\TestFile.txt”);
私有静态最终字符串行_DATA=“1111111 22222222 3333333 444444444 55555555 66666666 77777777 8888888 9999990000000000”;
公共静态void main(字符串[]args)引发IOException
{
如果(!FILE_TO_WRITE.getParentFile().exists())
{
抛出新的RuntimeException(“\n请在本地计算机上创建目录C:\\Temp\,并通过RemoteDesktop将C:\\作为“本地资源”运行此应用程序”;
}
文件_TO_WRITE.delete();
新建WriteOverTsClientDemo().execute();
}
私有void execute()引发IOException
{
System.out.println(“写入文件:+文件写入”);
System.out.println();
对于(int i=1;i我没有验证此效果的设置(没有窗口):(所以只考虑:

2GB听起来像是客户端与文件系统相关的最大文件大小.32位Windows操作系统

这种行为听起来像是在坏块FS上进行聪明的文件系统缓存:远程对大块的快速文件写入访问尝试聪明地占用文件,以尝试将将来对具有块的文件的写入固定在一起。是否尝试使用不同的FS进行验证

保持文件打开。重新打开以写入大型块可能会提示聪明的系统进行缓存

更新:

最终导致

作为本机的东西可以容纳任何bug。当涉及到中间的protocoll时。我宁愿在nio/Windows中将其作为bug归档,因为他们可能没有预见到RDP下面有任何有趣的事情

看起来返回的大小是
Integer.MAX\u VALUE
,文件指针移到了那里

替代实现
java.io.FileWriter
,不编码以减少代码行:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;

/**
 * Demonstrates weird issue when writing (appending) to a file over TsClient (Microsoft Remote Desktop).
 *
 * @author Martin
 */
public class WriteOverTsClientDemo
{
   // private static final File FILE_TO_WRITE = new File("\\\\tsclient\\C\\Temp\\TestFile.txt");
   private static final File FILE_TO_WRITE = new File("/tmp/TestFile.txt");

   private static final String ROW_DATA = "111111111122222222223333333333444444444555555555566666666667777777777888888888899999999990000000000";

   public static void main(final String[] args) throws IOException
   {
      if (!FILE_TO_WRITE.getParentFile().exists())
      {
         throw new RuntimeException("\nPlease create directory C:\\Temp\\ on your local machine and run this application via RemoteDesktop with C:\\ as a 'Local resource'.");
      }
      FILE_TO_WRITE.delete();
      new WriteOverTsClientDemo().execute();
   }

   private void execute() throws IOException
   {
      System.out.println("Writing to file: " + FILE_TO_WRITE);
      System.out.println();

      for (int i = 1; i <= 20; i++)
      {
         System.out.println("Writing batch " + i + "...");
         writeDataToFile(i);
         System.out.println("Size of file after batch " + i + ": " + FILE_TO_WRITE.length());
         System.out.println();
      }
      System.out.println("Done!");
   }

   private void writeDataToFile(final int batch) throws IOException
   {
      try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_TO_WRITE, batch > 1)))
      {
         writeData(batch, writer);
      }
   }

   private void writeData(final int batch, final BufferedWriter writer) throws IOException
   {
      for (final String data : createData())
      {
         writer.append(Integer.toString(batch));
         writer.append(" ");
         writer.append(data);
         writer.append("\n");
      }
   }

   private Iterable<String> createData()
   {
      return Collections.nCopies(100, ROW_DATA);
   }

}
导入java.io.BufferedWriter;
导入java.io.File;
导入java.io.FileWriter;
导入java.io.IOException;
导入java.util.Collections;
/**
*演示通过TsClient(Microsoft远程桌面)写入(附加)文件时出现的奇怪问题。
*
*@作者马丁
*/
公共类WriteOverTsClientDemo
{
//私有静态最终文件File TO WRITE=新文件(\\\\tsclient\\C\\Temp\\TestFile.txt);
私有静态最终文件File_TO_WRITE=新文件(“/tmp/TestFile.txt”);
私有静态最终字符串行_DATA=“1111111 22222222 3333333 444444444 55555555 66666666 77777777 8888888 9999990000000000”;
公共静态void main(最终字符串[]args)引发IOException
{
如果(!FILE_TO_WRITE.getParentFile().exists())
{
抛出新的RuntimeException(“\n请在本地计算机上创建目录C:\\Temp\,并通过RemoteDesktop将C:\\作为“本地资源”运行此应用程序”;
}
文件_TO_WRITE.delete();
新建WriteOverTsClientDemo().execute();
}
私有void execute()引发IOException
{
System.out.println(“写入文件:+文件写入”);
System.out.println();
对于(int i=1;i 1)))
{
writeData(批处理、写入程序);
}
}
私有void writeData(最终int批处理,最终BufferedWriter writer)引发IOException
{
for(最终字符串数据:createData())
{
writer.append(Integer.toString(batch));
作者。追加(“”);
writer.append(数据);
writer.append(“\n”);
}
}
私有Iterable createData()
{
返回集合.nCopies(100行,数据);
}
}

我们遇到了完全相同的问题,一位客户报告说,我们的java应用程序在写入TS客户端共享驱动器时会创建2GB文件。 我们注意到,只有在附加d时才会出现问题
static native long More ...size0(FileDescriptor fd) throws IOException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;

/**
 * Demonstrates weird issue when writing (appending) to a file over TsClient (Microsoft Remote Desktop).
 *
 * @author Martin
 */
public class WriteOverTsClientDemo
{
   // private static final File FILE_TO_WRITE = new File("\\\\tsclient\\C\\Temp\\TestFile.txt");
   private static final File FILE_TO_WRITE = new File("/tmp/TestFile.txt");

   private static final String ROW_DATA = "111111111122222222223333333333444444444555555555566666666667777777777888888888899999999990000000000";

   public static void main(final String[] args) throws IOException
   {
      if (!FILE_TO_WRITE.getParentFile().exists())
      {
         throw new RuntimeException("\nPlease create directory C:\\Temp\\ on your local machine and run this application via RemoteDesktop with C:\\ as a 'Local resource'.");
      }
      FILE_TO_WRITE.delete();
      new WriteOverTsClientDemo().execute();
   }

   private void execute() throws IOException
   {
      System.out.println("Writing to file: " + FILE_TO_WRITE);
      System.out.println();

      for (int i = 1; i <= 20; i++)
      {
         System.out.println("Writing batch " + i + "...");
         writeDataToFile(i);
         System.out.println("Size of file after batch " + i + ": " + FILE_TO_WRITE.length());
         System.out.println();
      }
      System.out.println("Done!");
   }

   private void writeDataToFile(final int batch) throws IOException
   {
      try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_TO_WRITE, batch > 1)))
      {
         writeData(batch, writer);
      }
   }

   private void writeData(final int batch, final BufferedWriter writer) throws IOException
   {
      for (final String data : createData())
      {
         writer.append(Integer.toString(batch));
         writer.append(" ");
         writer.append(data);
         writer.append("\n");
      }
   }

   private Iterable<String> createData()
   {
      return Collections.nCopies(100, ROW_DATA);
   }

}
#include <windows.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc < 2) {
        printf("Not enough args\n");
        return 1;
    }

    HANDLE hFile = CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD nw;
    OVERLAPPED ov;
    ov.Offset = (DWORD)0xFFFFFFFF;
    ov.OffsetHigh = (DWORD)0xFFFFFFFF;
    ov.hEvent = NULL;
    WriteFile(hFile, "a", 1, &nw, &ov);
    CloseHandle(hFile);

    return 1;
}