【问题标题】:Write HTML file using Java使用 Java 编写 HTML 文件
【发布时间】:2011-08-21 14:47:03
【问题描述】:

我希望我的 Java 应用程序在文件中编写 HTML 代码。现在,我正在使用 java.io.BufferedWriter 类对 HTML 标记进行硬编码。例如:

BufferedWriter bw = new BufferedWriter(new FileWriter(file));
bw.write("<html><head><title>New Page</title></head><body><p>This is Body</p></body></html>");
bw.close();

有没有更简单的方法可以做到这一点,因为我必须创建表格并且变得非常不方便?

【问题讨论】:

    标签: java html


    【解决方案1】:

    Velocity 是写这类东西的好人选。
    它允许您将 html 和数据生成代码尽可能分开。

    【讨论】:

      【解决方案2】:

      如果你愿意使用 Groovy,MarkupBuilder 对这类事情非常方便,但我不知道 Java 有类似的东西。

      http://groovy.codehaus.org/Creating+XML+using+Groovy's+MarkupBuilder

      【讨论】:

        【解决方案3】:

        这实际上取决于您正在创建的 HTML 文件的类型。

        对于此类任务,我使用创建一个对象,将其序列化为 XML,然后使用 XSL 对其进行转换。这种方法的优点是:

        • 源代码和HTML模板的严格分离,
        • 无需重新编译应用程序即可编辑 HTML,
        • 能够在不同情况下基于相同的 XML 提供不同的 HTML,甚至在需要时直接提供 XML(例如用于进一步的反序列化),
        • 要编写的代码量更短。

        缺点是:

        • 您必须了解 XSLT 并知道如何在 Java 中实现它。
        • 您必须编写 XSLT(这对许多开发人员来说是一种折磨)。
        • 使用 XSLT 将 XML 转换为 HTML 时,某些部分可能会比​​较棘手。几个例子:&lt;textarea/&gt; 标签(使页面无法使用)、XML 声明(可能导致 IE 出现问题)、空格(带有&lt;pre&gt;&lt;/pre&gt; 标签等)、HTML 实体(&amp;nbsp;)等。
        • 性能会降低,因为序列化为 XML 会浪费大量 CPU 资源,而且 XSL 转换的成本也很高。

        现在,如果您的 HTML 非常短或非常重复,或者如果 HTML 具有动态变化的可变结构,则不能考虑这种方法。另一方面,如果您提供结构相似的 HTML 文件,并且您希望减少 Java 代码的数量并使用模板,那么这种方法可能会奏效。

        【讨论】:

          【解决方案4】:

          我强烈建议您使用非常简单的模板语言,例如 Freemarker

          【讨论】:

            【解决方案5】:

            如果它正在成为重复性工作;我认为你应该做代码重用!为什么不简单地编写“编写”HTML 的小构建块的函数。明白了吗?参见例如。你可以有一个函数,你可以将一个字符串传递给它,它会自动将它放入一个段落标签并呈现它。当然,您还需要编写某种基本解析器来执行此操作(该函数如何知道将段落附加到何处!)。我不认为你是初学者..所以我没有详细说明...如果你不明白请告诉我..

            【讨论】:

              【解决方案6】:

              几个月前,我遇到了同样的问题,我发现的每个库都为我的最终目标提供了太多的功能和复杂性。所以我最终开发了我自己的库 - HtmlFlow - 它提供了一个非常简单和直观的 API,允许我以流畅的风格编写 HTML。在这里查看:https://github.com/fmcarvalho/HtmlFlow(它还支持 动态绑定到 HTML 元素)

              以下是将Task 对象的属性绑定到 HTML 元素的示例。考虑具有三个属性的Task Java 类:TitleDescriptionPriority,然后我们可以通过以下方式为 Task 对象生成 HTML 文档:

              import htmlflow.HtmlView;
              
              import model.Priority;
              import model.Task;
              
              import java.io.FileOutputStream;
              import java.io.IOException;
              import java.io.PrintStream;
              
              public class App {
              
                  private static HtmlView<Task> taskDetailsView(){
                      HtmlView<Task> taskView = new HtmlView<>();
                      taskView
                              .head()
                              .title("Task Details")
                              .linkCss("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css");
                      taskView
                              .body().classAttr("container")
                              .heading(1, "Task Details")
                              .hr()
                              .div()
                              .text("Title: ").text(Task::getTitle)
                              .br()
                              .text("Description: ").text(Task::getDescription)
                              .br()
                              .text("Priority: ").text(Task::getPriority);
                      return taskView;
                  }
              
                  public static void main(String [] args) throws IOException{
                      HtmlView<Task> taskView = taskDetailsView();
                      Task task =  new Task("Special dinner", "Have dinner with someone!", Priority.Normal);
              
                      try(PrintStream out = new PrintStream(new FileOutputStream("Task.html"))){
                          taskView.setPrintStream(out).write(task);
                          Desktop.getDesktop().browse(URI.create("Task.html"));
                      }
                  }
              }
              

              【讨论】:

              • 一个好主意,一个好工具,但不幸的是,许可证不是那么好,因此不能鼓励真正广泛使用...... ;)
              • @s-n-ushakov 抱歉,我不是许可协议方面的专家。 GPL v3.0 有什么问题?
              • GPL 的问题在于它过于严格。如果您只使用任何 GPL 许可代码,它也要求您在 GPL 下披露您的所有项目。这对于爱好或大学编程可能没有问题,但对于与业务相关的编程可能是一个相当大的问题。因此,为了使您的库更加商业友好,我可能建议至少将许可证更改为 LGPL,这不需要您将所有项目开源,而只需要披露您对库的改进。其他许可证,可能对商业更友好,包括 BSD、MIT、Apache、Eclipse...
              • @s-n-ushakov 我会将许可证更改为 MIT。感谢您的建议。
              • @s-n-ushakov 完成。只需发布 1.1 版即可。具有 MIT 许可证和一些小修复。
              【解决方案7】:

              如果你想自己做,不使用任何外部库,一个干净的方法是创建一个包含所有静态内容的 template.html 文件,例如:

              <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
              "http://www.w3.org/TR/html4/loose.dtd">
              <html>
              <head>
              <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
              <title>$title</title>
              </head>
              <body>$body
              </body>
              </html>
              

              为任何动态内容添加$tag 之类的标签,然后执行以下操作:

              File htmlTemplateFile = new File("path/template.html");
              String htmlString = FileUtils.readFileToString(htmlTemplateFile);
              String title = "New Page";
              String body = "This is Body";
              htmlString = htmlString.replace("$title", title);
              htmlString = htmlString.replace("$body", body);
              File newHtmlFile = new File("path/new.html");
              FileUtils.writeStringToFile(newHtmlFile, htmlString);
              

              注意:为简单起见,我使用了org.apache.commons.io.FileUtils

              【讨论】:

              • 对于 Java8,传递额外的 Charset.forName("UTF-8") 因为不推荐使用不带字符集的 readFileToString。
              • 也可以使用 MessageFormat 进行替换:String template = FileUtils.readFileToString(htmlTemplateFile); String title = "New Page"; String body = "This is Body"; String htmlString = MessageFormat.format(template, title, body);template 应包含 {0} 用于 title{1} 用于 body
              【解决方案8】:

              基于在内存中初步创建文档的模板和其他方法可能会对生成的文档大小施加某些限制。

              同时,基于 SAX 处理程序和默认的 XSLT 转换器,存在一种非常直接且可靠的即时写入方法来创建纯 HTML,后者具有 HTML 输出的内在能力:

              String encoding = "UTF-8";
              FileOutputStream fos = new FileOutputStream("myfile.html");
              OutputStreamWriter writer = new OutputStreamWriter(fos, encoding);
              StreamResult streamResult = new StreamResult(writer);
              
              SAXTransformerFactory saxFactory =
                  (SAXTransformerFactory) TransformerFactory.newInstance();
              TransformerHandler tHandler = saxFactory.newTransformerHandler();
              tHandler.setResult(streamResult);
              
              Transformer transformer = tHandler.getTransformer();
              transformer.setOutputProperty(OutputKeys.METHOD, "html");
              transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
              transformer.setOutputProperty(OutputKeys.INDENT, "yes");
              
              writer.write("<!DOCTYPE html>\n");
              writer.flush();
              tHandler.startDocument();
                  tHandler.startElement("", "", "html", new AttributesImpl());
                      tHandler.startElement("", "", "head", new AttributesImpl());
                          tHandler.startElement("", "", "title", new AttributesImpl());
                              tHandler.characters("Hello".toCharArray(), 0, 5);
                          tHandler.endElement("", "", "title");
                      tHandler.endElement("", "", "head");
                      tHandler.startElement("", "", "body", new AttributesImpl());
                          tHandler.startElement("", "", "p", new AttributesImpl());
                              tHandler.characters("5 > 3".toCharArray(), 0, 5); // note '>' character
                          tHandler.endElement("", "", "p");
                      tHandler.endElement("", "", "body");
                  tHandler.endElement("", "", "html");
              tHandler.endDocument();
              writer.close();
              

              请注意,XSLT 转换器会让您摆脱转义特殊字符(如 &gt;)的负担,因为它会自行处理必要的问题。

              而且很容易将像 startElement()characters() 这样的 SAX 方法包装成更符合个人口味的东西......

              【讨论】:

              • 只使用标准工具的好主意。不幸的是,写tHandler.startElement("", "", "p", new AttributesImpl()) 很乏味——更糟糕的是,如果想在一个元素上设置一个 CSS 类......
              • @haui 嗯,这只是一个想法。可以围绕这些标准调用定义一些速记包装器,以节省一些打字或复制粘贴... :)
              【解决方案9】:

              您可以使用基于jsoupwffweb (HTML5) 的。

              jsoup 的示例代码:-

              Document doc = Jsoup.parse("<html></html>");
              doc.body().addClass("body-styles-cls");
              doc.body().appendElement("div");
              System.out.println(doc.toString());
              

              打印

              <html>
               <head></head>
               <body class=" body-styles-cls">
                <div></div>
               </body>
              </html>
              

              wffweb 的示例代码:-

              Html html = new Html(null) {{
                  new Head(this);
                  new Body(this,
                      new ClassAttribute("body-styles-cls"));
              }};
              
              Body body = TagRepository.findOneTagAssignableToTag(Body.class, html);
              body.appendChild(new Div(null));
              
              System.out.println(html.toHtmlString());
              //directly writes to file
              html.toOutputStream(new FileOutputStream("/home/user/filepath/filename.html"), "UTF-8");
              

              打印(缩小格式):-

              <html>
              <head></head>
              <body class="body-styles-cls">
                  <div></div>
              </body>
              </html>
              

              【讨论】:

                【解决方案10】:

                我也很难找到一些简单的东西来满足我的需求,所以我决定编写自己的库(使用 MIT 许可证)。 它主要基于复合和构建器模式。

                一个基本的声明性示例是:

                import static com.github.manliogit.javatags.lang.HtmlHelper.*;
                
                html5(attr("lang -> en"),
                  head(
                    meta(attr("http-equiv -> Content-Type", "content -> text/html; charset=UTF-8")),
                    title("title"),
                    link(attr("href -> xxx.css", "rel -> stylesheet"))
                  )
                ).render();
                

                一个流畅的例子是:

                ul()
                  .add(li("item 1"))
                  .add(li("item 2"))
                  .add(li("item 3"))     
                

                您可以查看更多示例here

                我还创建了一个on line converter 来动态转换每个 html sn-p(从复杂的引导模板到简单的单个sn-p)(即html -> javatags)

                【讨论】:

                • 作品会,非常优雅!
                • attr("href -&gt; xxx.css",... 给人的印象是,该库会产生用于写入的解析开销。为什么不attrs(attr("href", "xxx.css"), ...)
                猜你喜欢
                • 1970-01-01
                • 2015-09-23
                • 2016-07-17
                • 1970-01-01
                • 2023-03-23
                • 2010-09-27
                • 2015-07-06
                • 1970-01-01
                • 2014-11-19
                相关资源
                最近更新 更多