6

所以我试图将消息网络上用户的消息写入文件。我正在尝试使用良好的 java 实践和适当的文件 IO 技术来构建这个程序。

目前我的程序识别出有人发布了一条消息,接收该消息并立即将其写入文件。创建文件对象,创建写入器对象,附加消息,然后关闭文件。如果没有很多消息进入,这似乎是一个很好的做法,但如果有一个快速的对话流,这似乎很慢并且需要很多不必要的操作,因为该文件将立即再次打开。

然后我想如果我只是让文件保持打开状态并在消息到达文件时将它们写入,然后定期关闭它会怎样。这是好习惯吗?长时间打开文件?例如在一小时后或写入一定数量的数据后?

现在,我想我应该获取消息,将它们存储在“缓存”(如字符串数组)中,然后在“缓存”已满时将字符串数组保存到文件中。这是更好的做法吗?

所以我有两个问题:

1)如果您不使用该文件,那么长时间(几分钟到几小时)打开文件是一种好习惯吗?

2)像我说的“缓存”有什么好的做法?字符串数组好吗?我应该使用更好的东西吗?您将如何存储这些信息?

4

3 回答 3

3

长时间打开文件绝对没问题。这肯定比反复打开和关闭它要好得多。单个打开文件消耗的资源量可以忽略不计;您唯一担心的是您是否有很多打开的文件(数百或数千)。我建议您在程序启动时打开文件,并在程序完成时关闭它。

如果您使用合适的工具来检查您的程序或系统上的其他程序持有的打开文件,您会发现它们都持有一些文件(几个到几十个)在其整个生命周期中打开 - 任何包含程序的代码(可执行文件、共享库和 Java 程序的 JAR 文件),因为这些代码被打开,然后进行内存映射,并且通常也是日志文件。这是正常和安全的。

现在,您将需要在此期间刷新流(或 writer,或RandomAccessFile,或任何您使用的东西)。每当您需要确保写入该点的所有数据都已安全写入磁盘时,您都应该这样做;这可能是在每条消息之后,或者在您认为合适的给定数量的消息、数据量或时间段之后。

于 2012-12-20T00:42:32.237 回答
3

在我看来,服务器应用程序中日志(和类似的)的最佳实践是确定一个可接受的时间延迟并坚持下去。例如,如果您设置 5 秒延迟,请编写代码,以便:

  • 如果您在日志中写入内容,它将在 5 秒内“真正”写入。
  • 如果在 5 秒之前写入了其他内容,它只会被添加到缓冲区中(在时间到时写入)。

这样,您每 5 秒最多只能执行一次磁盘写入,但它肯定是写入的。这与其他方法相比很好:

  • 如果每次写入任何内容时都将数据刷新到磁盘,但负载增加并且每秒有 10,000 个事件,那么每秒 10,000 次磁盘写入将浪费 I/O 时间。
  • 如果您将它留给 Java/操作系统来决定何时刷新数据,但负载非常低(例如在半夜),那么日志甚至可能已经过时数小时。(如果有一个事件,不足以填满缓冲区,那么几个小时内什么都没有。)

我最近没有查看 API 是否有内置的方法来执行此策略,但它很容易编码。顺便说一句,不需要手动缓存输出;您可以只使用 BufferedOutputStream,并在您想将其写入磁盘时调用 flush() 对象。(这样它也会在达到缓冲区限制时自动写入,但如果你明智地选择限制,那可能没问题。)

关于让文件保持打开状态,您可以根据需要让文件保持打开状态(当您不再写入时将其关闭)。假设您没有打开数千个文件,并且不需要多个应用程序写入同一个文件,这不会导致任何问题。

于 2012-12-20T00:46:42.460 回答
1

1)如果您不使用该文件,那么长时间(几分钟到几小时)打开文件是一种好习惯吗?

我认为这取决于有多少消息进入您的程序以及每个消息的大小。如果你的记忆可以满足你的计算,你可以考虑一下。但是当每条消息到来(可能是一个blob)时,我会考虑在数据库上写入。还要考虑如果您在写入文件时程序崩溃会发生什么。您可能会丢失存储在内存中的整条消息。

2)像我说的“缓存”有什么好的做法?字符串数组好吗?我应该使用更好的东西吗?您将如何存储这些信息?

如果您将数据临时存储在内存数组中,那么当您知道大小时就可以了。否则你可以使用 ArrayList。

于 2012-12-20T00:33:41.527 回答