模板引擎:ftl文件生成word

news2024/12/23 6:31:00

wshanshi:总结记录…便于回顾…

一、什么是FreeMarker

FreeMarker 是一个用 Java 语言编写的模板引擎,基于模板来生成文本输出。

FreeMarker的原理:模板+数据模型=输出,模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。

在这里插入图片描述

二、FreeMarker优点

FreeMarker的诞生是为了取代JSP,降低了表现层和业务逻辑的耦合,提高了效率。

2.1、表现层、业务逻辑分离

FreeMarker职责明确,功能专注,仅仅负责页面的展示,从而去掉了繁琐的逻辑代码。

2.2、降低耦合度

JSP页面前后端的代码写到了一起,耦合度很高,前端开发需要熟悉后台环境,需要去调试,而后台开发人员需要去做不熟悉的前端界面设计。对两者而言,交替性的工作需要花费一定的学习成本,效率低下。而使用FreeMarker后,前后端完全分离,大家各干各的,互不影响。

2.3、简单易用,功能强大

FreeMarker支持JSP标签,同时内置了大量常用功能,比如html过滤,日期金额格式化等等。FreeMarker代码十分简洁,上手快,使用非常方便。

三、FreeMarker常用语法

在FreeMarker模板语言中,使用插值${…}将数据模型中的部分替代输出。

3.1、内置函数

内建函数:http://freemarker.foofun.cn/ref_builtins_string.html

在这里插入图片描述
在这里插入图片描述

<#–非空判断2种写法示例–>

<p>【姓名】:${name?if_exists?html}</p>

<p>【性别】:${sex!?html}</p>

在这里插入图片描述

3.2、数值类型

<p>【年龄(数值)】:${age?string.number}</p>

<p>【存款(¥)】:${age?string.currency}</p>

在这里插入图片描述

3.3、日期类型

FreeMarker中可以分别对date、time、datetime三种类型的日期时间设置格式。

config.setDateTimeFormat("yyyy-MM-dd HH:mm:ss");  
config.setDateFormat("yyyy-MM-dd");  
config.setTimeFormat("HH:mm:ss");

年月日:<td>${(f.birthday?string('yyyy-MM-dd'))!}</td>
时分秒:<td>${(f.birthday?string('HH:mm:ss'))!}</td>
年月日:<td>${(f.birthday?string('yyyy-MM-dd HH:mm:ss'))!}</td>

在这里插入图片描述

3.4、默认值设置

默认值设置的2种方法:

<p>【默认值】方法1:${default?default('这是一个默认值')}</p>
<p>【默认值】方法2:${default!('这是一个默认值')}</p>

在这里插入图片描述

3.5、拼接输出

拼接输出的2种方法:

<p>【变量拼接】方法1:${"拼接下地址:"+address!}</p>
<p>【变量拼接】方法2:${"拼接下地址:${address!}"}</p>

在这里插入图片描述

3.6、if判断

<#if f.sex =='1'>
    ${'男'}
<#elseif f.sex =='2'>
    ${'女'}
<#else>
    ${'未知'}
</#if>

3.7、list遍历

<#list friends as f>
    <tr>
        <td>${f.name?if_exists?html}</td>
        <td>${f.age?if_exists?html}</td>
        <td>${f.sex?if_exists?html}</td>
        <#--设置日期-->
        <td>${(f.birthday?string('yyyy-MM-dd'))!}</td>
        </br>
    </tr>
</#list>

3.8、list排序

<#--list升序:sort_by函数。sort对序列(sequence)进行排序,要求序列中的变量必须是:字符串(按首字母排序),数字,日期值-->
<#list friends?sort_by("age") as f>
    <tr>
        <td>${f.name?if_exists?html}</td>
        <td>${f.age?if_exists?html}</td>
        <td>${f.sex?if_exists?html}</td>
        <#--设置日期-->
        <td>${(f.birthday?string('HH:mm:ss'))!}</td>
        </br>
    </tr>
</#list>
<#--list降序:reverse降序排序-->
<#list friends?sort_by("age")?reverse as f>
    <tr>
        <td>${f.name?if_exists?html}</td>
        <td>${f.age?if_exists?html}</td>
        <td>${f.sex?if_exists?html}</td>
        <#--设置日期-->
        <td>${(f.birthday?string('yyyy-MM-dd HH:mm:ss'))!}</td>
        </br>
    </tr>
</#list>

四、FreeMarker使用

4.1、使用过程(核心简要)

说明:以下步骤,可以封装到一个工具类当中。主要操作:读取指定模板、数据填充、输出文件。

// 第一步:创建一个Configuration对象,直接new一个对象。构造方法的参数就是FreeMarker对应的版本号。
Configuration configuration = new Configuration(Configuration.getVersion());
 
// 第二步:设置模板文件所在的路径。
configuration.setDirectoryForTemplateLoading(new File("/WEB-INF/ftl"));
 
// 第三步:设置模板文件使用的字符集。一般就是utf-8.
configuration.setDefaultEncoding("utf-8");
 
// 第四步:加载一个模板,创建一个模板对象。
Template template = configuration.getTemplate("hello.ftl");
 
// 第五步:创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map。
Map dataModel = new HashMap<>();
//向数据集中添加数据
dataModel.put("hello", "this is my first FreeMarker test.");
 
// 第六步:创建一个Writer对象,一般创建一FileWriter对象,指定生成的文件名。
Writer out = new FileWriter(new File("/hello.html"));
 
// 第七步:调用模板对象的process方法输出文件。
template.process(dataModel, out);
 
// 第八步:关闭流。
out.close();

4.2、html填充使用

<script src="https://cdn.staticfile.org/jquery/2.2.4/jquery.min.js" xmlns="http://www.w3.org/1999/html"
        xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html"></script>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>测试模板引擎</title>
</head>
<body>
<h1>测试模板引擎</h1>
<#--非空判断2种写法:变量存在,输出该变量,否则不输出-->
<p>【姓名】:${name?if_exists?html}</p>
<p>【性别】:
    <#if sex =='1'>
        ${'男'}
    <#elseif sex =='2'>
        ${'女'}
    <#else>
        ${'未知'}
    </#if>
</p>
<#--数字输出-->
<p>【年龄(数值)】:${age?string.number}</p>
<p>【存款(¥)】:${age?string.currency}</p>
<p>【生日(文本)】:${birthday?if_exists?html} </p>
<p>【地址】:${address?if_exists?html}</p>

<#--设置默认值2种写法-->
<p>【默认值】方法1:${default?default('这是一个默认值')}</p>
<p>【默认值】方法2:${default!('这是一个默认值')}</p>
<#--拼接输出2种写法-->
<p>【变量拼接】方法1:${"拼接下地址:"+address!}</p>
<p>【变量拼接】方法2:${"拼接下地址:${address!}"}</p>
<table border="0">
    <tr>
        <th>姓名</th>
        <th>年龄</th>
        <th>性别</th>
        <th>生日</th>
    </tr>
    <#--list遍历-->
    <#list friends as f>
        <tr>
            <td>${f.name?if_exists?html}</td>
            <td>${f.age?if_exists?html}</td>
            <td>
                <#if f.sex =='1'>
                    ${'男'}
                <#elseif f.sex =='2'>
                    ${'女'}
                <#else>
                    ${'未知'}
                </#if>
            </td>
            <#--设置日期-->
            <td>${(f.birthday?string('yyyy-MM-dd'))!}</td>
            </br>
        </tr>
    </#list>
    <#--list升序:sort_by函数。sort对序列(sequence)进行排序,要求序列中的变量必须是:字符串(按首字母排序),数字,日期值-->
    <#list friends?sort_by("age") as f>
        <tr>
            <td>${f.name?if_exists?html}</td>
            <td>${f.age?if_exists?html}</td>
            <td>
                <#if f.sex =='1'>
                    ${'男'}
                <#elseif f.sex =='2'>
                    ${'女'}
                <#else>
                    ${'未知'}
                </#if>
            </td>
            <#--设置日期-->
            <td>${(f.birthday?string('HH:mm:ss'))!}</td>
            </br>
        </tr>
    </#list>
    <#--list降序:reverse降序排序-->
    <#list friends?sort_by("age")?reverse as f>
        <tr>
            <td>${f.name?if_exists?html}</td>
            <td>${f.age?if_exists?html}</td>
            <td>
                <#if f.sex =='1'>
                    ${'男'}
                <#elseif f.sex =='2'>
                    ${'女'}
                <#else>
                    ${'未知'}
                </#if>
            </td>
            <#--设置日期-->
            <td>${(f.birthday?string('yyyy-MM-dd HH:mm:ss'))!}</td>
            </br>
        </tr>
    </#list>
</table>
</body>
</html>

4.3、word文件生成使用

对于项目当中一些复杂的指定模板word生成,可用模板引擎实现。

4.3.1、定义模板

说明:将需要生成的word定义好样式,排版等。如下图所示:

在这里插入图片描述

4.3.2、定义占位符

说明:将表格内容用占位符进行填充,如${xxxx}。xxxx一般为实体类的某个属性。

正常设置放实体属性就好了,如下图的“registerTime”,如果有特殊符号,直接在模板中添加上,如下图中的复选框。

在这里插入图片描述

4.3.3、改文件后缀

定义完占位符后,将该文件另存为xml后缀文件。改为xml文件后,可操作格式化一下,否则很乱。格式化之后,将该文件改为ftl文件。

注意:一定注意改后缀之后,占位符${}有没有被分开。否则后面获取模板进行填充时会有问题。

4.3.4、代码操作

4.3.4.1、maven依赖
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-freemarker</artifactId>
  </dependency>
  <dependency>
     <groupId>org.freemarker</groupId>
     <artifactId>freemarker</artifactId>
     <version>2.3.30</version>
  </dependency>
4.3.4.2、application配置
spring:
    freemarker:
    charset: utf-8
    suffix: .ftl
    template-loader-path: classpath:/templates/
4.3.4.3、操作类定义

上述步骤中已定义了占位符,一般会将这所有占位符定义为一个实体类。

在这里插入图片描述

4.3.4.4、接口定义

根据需求定义传参即可。比如传参编号进行查询之类的。

void download(HttpServletRequest request, HttpServletResponse response);

4.3.4.5、实现类定义

此处为模拟的数据,具体业务时,可从对应库表查出数据。

@Service
public class ExportDataServiceImpl implements ExportDataService {
    @Override
    public void download(HttpServletRequest request, HttpServletResponse response) {
        ExportData exportData = ExportData.builder().company("某公司").project("关于疫情期间补贴的事项").registerTime(new Date()).registerAddress("上海市浦东新区")
                .registerZB("222.22").beforeYearNS("2323.232").contant("wss").phone("13234567899").type("1").idCard("232323232323").total(999).jsPepole(34).scPeople(22).otherPeople(44).build();

        Map<String, Object> map = setMap(exportData);
        try {
            WordUtils.exportMillCertificateWord(request, response, map, "apply1.ftl", this.getClass());
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private Map<String, Object> setMap(ExportData exportData) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "申请表");
        map.put("company", exportData.getCompany());
        map.put("project", exportData.getProject());
        map.put("registerTime", exportData.getRegisterTime());
        map.put("registerAddress", exportData.getRegisterAddress());
        map.put("registerZB", exportData.getRegisterZB());
        map.put("beforeYearNS", exportData.getBeforeYearNS());
        map.put("contant", exportData.getContant());
        map.put("phone", exportData.getPhone());
        map.put("type", exportData.getType());
        map.put("idCard", exportData.getIdCard());
        map.put("total", exportData.getTotal());
        map.put("jsPepole", exportData.getJsPepole());
        map.put("scPeople", exportData.getScPeople());
        map.put("otherPeople", exportData.getOtherPeople());

        List<Map<String, Object>> checkboxList = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("label", "新一代信息技术");
        map1.put("value", 1);
        checkboxList.add(map1);
        Map<String, Object> map2 = new HashMap<>();
        map2.put("label", "高端装备制造");
        map2.put("value", 0);
        checkboxList.add(map2);
        Map<String, Object> map3 = new HashMap<>();
        map3.put("label", "绿色低碳");
        map3.put("value", 1);
        checkboxList.add(map3);
        Map<String, Object> map4 = new HashMap<>();
        map4.put("label", "生物医药");
        map4.put("value", 0);
        checkboxList.add(map4);
        Map<String, Object> map5 = new HashMap<>();
        map5.put("label", "数字经济");
        map5.put("value", 0);
        checkboxList.add(map5);
        Map<String, Object> map6 = new HashMap<>();
        map6.put("label", "新材料");
        map6.put("value", 1);
        checkboxList.add(map6);
        Map<String, Object> map7 = new HashMap<>();
        map7.put("label", "海洋经济");
        map7.put("value", 1);
        checkboxList.add(map7);
        Map<String, Object> map8 = new HashMap<>();
        map8.put("label", "文化创意");
        map8.put("value", 1);
        checkboxList.add(map8);
        map.put("labels", checkboxList);
        return map;
    }
}
4.3.4.6、控制层定义
@GetMapping("/download")
public void download(HttpServletRequest request, HttpServletResponse response) {
    exportDataService.download(request, response);
}
4.3.4.7、工具类
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;

import cn.hutool.core.io.FileUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;

@Component
public class WordUtils {
    private static final Configuration CONFIGURATION;

    static {
        Version incompatibleImprovements = new Version("2.3.29");
        CONFIGURATION = new Configuration(incompatibleImprovements);
        CONFIGURATION.setDefaultEncoding("utf-8");
    }

    public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map, String ftlName, Class<?> getClass) throws IOException {
        CONFIGURATION.setClassForTemplateLoading(getClass, "/models/");
        Template freemarkerTemplate = CONFIGURATION.getTemplate(ftlName, "utf-8");
        File file = null;
        ServletOutputStream out = null;
        try {
            // 调用工具类的createDoc方法生成Word文档
            file = createDoc(map, freemarkerTemplate);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            // 设置浏览器以下载的方式处理该文件名
            String fileName = map.get("name") + ".doc";
            response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
            out = response.getOutputStream();
            FileUtil.writeToStream(file, out);
        } finally {
            if (out != null) {
                out.close();
            }
            if (file != null) {
                file.delete();
            }
        }
    }

    private static File createDoc(Map<?, ?> dataMap, Template template) {
        String name = "/test.doc";
        File f = new File(name);
        try {
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8);
            template.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
        return f;
    }
}

4.3.5、运行效果

数据会根据自定义占位符+相关语法定义,填充数据到对应的模板位置中。

在这里插入图片描述

五、注意事项

5.1、空值判断

报异常:freemarker.core.ParseException: Syntax error in template “test.ftl” in line 1695, column 53:Encountered “/”, but was expecting one of:

说明:word中定义完占位符后,改后缀为xml文件、ftl文件后,${}可能会被分隔开。需仔细检查。

异常信息如下:

freemarker.core.ParseException: Syntax error in template "test.ftl" in line 1695, column 53:
Encountered "/", but was expecting one of:
<STRING_LITERAL>
<RAW_STRING>
"false"
"true"
<INTEGER>
<DECIMAL>
"."
"+"
"-"
"!"
"["
"("
"{"
<ID>

如下图所示:

在这里插入图片描述

原因:FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,没有被赋值的变量就会抛出异常,因为FreeMarker未赋值的变量强制出错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误.这里所说的空值,实际上也包括那些并不存在的变量,对于一个Java的 null值而言,我们认为这个变量是存在的,只是它的值为null,但对于FreeMarker模板而言,它无法理解null值,null值和不存在的变量完全相同。

解决方法:把占位符补充完整,多的}删掉,否则会乱掉。

5.2、非必填

有些数据可能是非必填的,对于文本类型空值模板数据填充。有两种解决方法:

1、设置下占位符判断是否为空。<w:t>${CYR?if_exists?html}</w:t>
2、在数据填充时进行非空判断,为空赋值“”。

5.3、日期非空判断

日期非空判断(非必填),记得加判断。日期建议使用java.util.Date 类型。
${(f.birthday?string(‘yyyy-MM-dd’))!}

六、参考文档

相关文档:http://www.freemarker.net/

相关文档:http://freemarker.foofun.cn/ref_directive_if.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式之组合模式

Composite design pattern 组合模式的概念、组合模式的结构、组合模式的优缺点、组合模式的使用场景、组合模式的实现示例、组合模式的源码分析 1、组合模式的概念 组合模式&#xff0c;即部分整体模式&#xff0c;是用于把一组相似的对象当做一个单一个的对象。组合模式依据树…

C#语言实例源码系列-身份证验证

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

【车载开发系列】UDS诊断---数据传输($0x36)

【车载开发系列】UDS诊断—数据传输&#xff08;$0x36&#xff09; UDS诊断---数据传输&#xff08;$0x36&#xff09;【车载开发系列】UDS诊断---数据传输&#xff08;$0x36&#xff09;一.概念定义二.报文格式1&#xff09;请求报文2&#xff09;肯定响应3&#xff09;否定响…

FL Studio21最新中文公测版下载及新功能介绍

FL Studio水果21现已推出&#xff0c;提供更快、更精确的音频编辑&#xff0c;coco玛奇朵升级后的DAW为用户提供了更多的内容发现和改进的界面。 Image-Line发布了FL Studio 21&#xff0c;称其可以实现更快、更精确的音频编辑&#xff0c;以及对整个DAW的更多控制。 期待已久…

【毕业设计_课程设计】基于SSM的实验室管理系统(源码+论文)

文章目录0 项目说明1 研究目的2 研究方法3 项目使用4 研究结论5 论文目录6 项目源码0 项目说明 基于SSM的实验室管理系统 提示&#xff1a;适合用于课程设计或毕业设计&#xff0c;工作量达标&#xff0c;源码开放 1 研究目的 基于B/S模式的实验室管理系统&#xff0c;它所覆…

Linux命令行笔记-00 综述

文章目录1 Linux命令行简介1.1 Linux命令行的分类1.1.1 根据系统中作用来分类1.1.2 根据对象来分类2 Linux命令行解释器2.1 命令行解释器shell2.1.1 核心程序2.1.2 公用程序shell2.1.3 用户的默认shell2.1.4 shell如何工作2.2 Shell发展历史2.3 shell版本的差异2.3.1 C shell2.…

云原生----什么是云原生

【原文链接】云原生----什么是云原生 文章目录1. 云原生的概念2. 云原生的四要素3. 云原生的关键目标什么是云原生&#xff1f;这里将从云原生的概念、云原生的四要素、云原生关键目标等方面介绍。1. 云原生的概念 云原生应用时面向云而设计的应用&#xff0c;在使用云原生技术…

Metasploit Framework和msf框架

Metasploit Framework ● MSF默认集成与kali linux之中 ● 使用postgresql数据库存储数据 ○ 早期版本需要先启动数据库再启动msf MSF架构 Rex ● 基本功能库&#xff0c;用于完成日常基本任务&#xff0c;无需人工手动编码实现 ● 处理socket连接访问、协议应答&#xff08…

洛谷千题详解 | P1020 [NOIP1999 普及组] 导弹拦截【C++语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; C源码2&#xff1a; -------------------------------------------------------------------------------------------------…

【(C语言)数据结构奋斗100天】栈和队列

前言 &#x1f3e0;个人主页&#xff1a;泡泡牛奶 &#x1f335;系列专栏&#xff1a;[C语言] 数据结构奋斗100天 本期所介绍的是栈和队列&#xff0c;那么什么是栈呢&#xff0c;什么是队列呢&#xff1f;在知道答案之前&#xff0c;请大家思考一下下列问题&#xff1a; 你如何…

【问答篇】Java 线程篇 面试题(二)

每天进步一点~ (ps: 文章内容及图片出处来自本人公众号~) 01、问&#xff1a;请谈谈你对线程声明周期的6种状态的认识和理解 答&#xff1a;很多地方说线程有5种状态&#xff0c;但实际上是6种状态:NEW、RUNNABLE, BLOCKED、 WAITING、TIMED_WAITING、TERMINATED; 新创建&a…

(附源码)Springboot掌上博客系统 毕业设计 063131

Springboot掌上博客系统的设计与实现 摘 要 掌上博客系统是当今网络的热点&#xff0c;博客技术的出现使得每个人可以零成本、零维护地创建自己的网络媒体&#xff0c;Blog站点所形成的网状结构促成了不同于以往社区的Blog文化&#xff0c;Blog技术缔造了“博客”文化。 本文课…

微服务框架 SpringCloud微服务架构 服务异步通讯 53 MQ 集群 53.1 集群分类 53.2 普通集群

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 服务异步通讯 文章目录微服务框架服务异步通讯53 MQ 集群53.1 集群分类53.1.1 集群分类53.2 普通集群53.2.1 普通集群53.2.2 搭建普通 集群5…

2022 FIFA World Cup Final

我希望梅西能够捧杯&#xff0c;因为我怕再看见那个眼神&#xff01;写在总决赛开始前 12/18/2022 22:04 在一个周日的晚上收到了邹总发的活动信&#xff0c;我记得还在CSDN问答区在回答问题&#xff0c;突然看见私信的红点&#xff0c;其实看到活动&#xff08;活动链接点击这…

万字长文,彻底搞懂分布式缓存Redis

最近系统性地整理了Redis的知识点&#xff0c;在此和大家做些分享&#xff0c;希望能帮助到大家。 为什么Redis这么受欢迎 时代产物 随着互联网规模的不断扩张&#xff0c;越来越多的企业在技术架构上会采用分布式架构&#xff0c;而且对于系统的吞吐量以及响应速率的要求也…

非零基础自学Golang 第11章 文件操作 11.2 文件基本操作 11.2.3 文件写入 11.2.4 删除文件

非零基础自学Golang 文章目录非零基础自学Golang第11章 文件操作11.2 文件基本操作11.2.3 文件写入11.2.4 删除文件第11章 文件操作 11.2 文件基本操作 11.2.3 文件写入 与之前的文件读取相比&#xff0c;向文件写入内容也有两个接口&#xff0c;分别为Write和WriteAt。 fu…

数据管理篇之元数据

第12章 元数据 1.元数据概述 元数据定义 元数据是关于数据的数据。按照用途可以分为两类&#xff1a; 技术元数据 业务元数据 阿里巴巴常见的技术元数据&#xff1a; 分布式计算系统存储元数据 分布式计算系统运行元数据 数据开发平台中数据同步&#xff0c;计算任务、任务调…

【编译原理】第四章部分课后题答案

第 四 章 课 后 习 题 T 4.1 根据表4.1的语法制导定义&#xff0c;为输入表达式5∗(4∗32)5*(4*32)5∗(4∗32)构造注释分析树。 T 4.2 构造表达式((a∗b)(c))((a*b)(c))((a∗b)(c))的分析树和语法树&#xff1a; &#xff08;a&#xff09;根据表4.3的语法制导定义。 &…

C++中你不知道的namespace和using的用法

目录 引言 一: 冒号作用域 二、名字控制 1 命令空间 2 命令空间的使用 三、 using的指令 1 using的声明 2 using的编译指令 引言 你是不是只认为namespace 和 using 在C中是基本的语法框架&#xff0c;但是却不知道它们的真正用法&#xff0c;看完文章你会对using和name…

计算机毕设Python+Vue校园志愿者服务系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…