首页 > 其他分享 >读写CSV文件

读写CSV文件

时间:2022-09-29 15:58:45浏览次数:41  
标签:文件 null string 读写 System ._ using CSV public

来源:https://www.cnblogs.com/lxhbky/p/12219080.html

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace StockCheckApp.Utils
{
    public sealed class CsvHelper
    {
        private static readonly CsvHelper instance = new CsvHelper();
        public static CsvHelper getInstance()
        {
            return instance;
        }

        /// <summary>
        /// 日志
        /// </summary>
        //private ILogger _Logger { get; set; }
        //public CsvHelper(ILogger<CsvHelper> logger)
        //{
        //    this._Logger = logger;
        //}
        private CsvHelper() { }

        public List<T> Read<T>(string filePath, CsvFileDescription fileDescription) where T : class, new()
        {
            List<T> tList = new List<T>(50 * 10000);

            T t = null;
            int currentRawIndex = 0;

            if (File.Exists(filePath))
            {
                using (StreamReader streamReader = new StreamReader(filePath, fileDescription.Encoding))
                {
                    Dictionary<int, FieldMapper> fieldMapperDic = FieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.CSVTitleIndex);
                    string rawValue = null;
                    string[] rawValueArray = null;
                    PropertyInfo propertyInfo = null;
                    string propertyValue = null;
                    bool rawReadEnd = false;

                    bool isExistSplitChart = false;
                    do
                    {
                        rawValue = streamReader.ReadLine();

                        //标题行
                        if (currentRawIndex > fileDescription.TitleRawIndex)
                        {
                            if (!string.IsNullOrEmpty(rawValue))
                            {
                                //替换字符串含有分隔符为{分隔符},最后再替换回来
                                if (rawValue.Contains("\""))
                                {
                                    isExistSplitChart = true;

                                    int yhBeginIndex = 0;
                                    int yhEndIndex = 0;
                                    string yhText = null;
                                    do
                                    {
                                        yhBeginIndex = StringHelper.GetIndexOfStr(rawValue, "\"", 1);
                                        yhEndIndex = StringHelper.GetIndexOfStr(rawValue, "\"", 2);
                                        yhText = rawValue.Substring(yhBeginIndex, (yhEndIndex - yhBeginIndex + 1));
                                        string newYHText = yhText.Replace("\"", "").Replace(fileDescription.SeparatorChar.ToString(), "{分隔符}");
                                        rawValue = rawValue.Replace(yhText, newYHText);
                                    } while (rawValue.Contains("\""));
                                }

                                rawValueArray = rawValue.Split(fileDescription.SeparatorChar);

                                t = new T();
                                foreach (var fieldMapper in fieldMapperDic)
                                {
                                    propertyInfo = fieldMapper.Value.PropertyInfo;
                                    propertyValue = rawValueArray[fieldMapper.Key];
                                    if (!string.IsNullOrEmpty(propertyValue))
                                    {
                                        try
                                        {
                                            if (isExistSplitChart && propertyValue.Contains("{分隔符}"))
                                            {
                                                propertyValue = propertyValue.Replace("{分隔符}", fileDescription.SeparatorChar.ToString());
                                            }

                                            TypeHelper.SetPropertyValue(t, propertyInfo.Name, propertyValue);
                                        }
                                        catch (Exception e)
                                        {
                                            string msg = $"第{currentRawIndex + 1}行数据{propertyValue}转换属性{propertyInfo.Name}-{propertyInfo.PropertyType.Name}失败!";
                                            //this._Logger.LogWarning(e, msg);
                                            //continue;
                                            throw new Exception(msg);
                                        }
                                    }
                                }
                                tList.Add(t);
                            }
                            else
                            {
                                rawReadEnd = true;
                            }
                        }
                        currentRawIndex++;
                    } while (rawReadEnd == false);
                }
            }


            return tList;
        }

        public void WriteFile<T>(string path, List<T> tList, CsvFileDescription fileDescription) where T : class, new()
        {
            if (!string.IsNullOrEmpty(path))
            {
                string fileDirectoryPath = null;
                if (path.Contains("\\"))
                {
                    fileDirectoryPath = path.Substring(0, path.LastIndexOf('\\'));
                }
                else
                {
                    fileDirectoryPath = path.Substring(0, path.LastIndexOf('/'));
                }
                if (!Directory.Exists(fileDirectoryPath))
                {
                    Directory.CreateDirectory(fileDirectoryPath);
                }

                int dataCount = tList.Count;
                Dictionary<int, FieldMapper> fieldMapperDic = FieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.CSVTitleIndex);
                int titleCount = fieldMapperDic.Keys.Count;//.Max();
                string[] rawValueArray = new string[titleCount];
                StringBuilder rawValueBuilder = new StringBuilder();
                string rawValue = null;
                T t = null;
                PropertyInfo propertyInfo = null;
                int currentRawIndex = 0;
                int tIndex = 0;

                using (StreamWriter streamWriter = new StreamWriter(path, false, fileDescription.Encoding))
                {
                    do
                    {
                        try
                        {
                            rawValue = "";

#if DEBUG
                            if (currentRawIndex % 10000 == 0)
                            {
                                string msg = $"已写入文件:{path},数据量:{currentRawIndex}";
                                //this._Logger.LogInformation(msg);
                            }
#endif

                            if (currentRawIndex >= fileDescription.TitleRawIndex)
                            {
                                //清空数组数据
                                for (int i = 0; i < titleCount; i++)
                                {
                                    rawValueArray[i] = "";
                                }

                                if (currentRawIndex > fileDescription.TitleRawIndex)
                                {
                                    t = tList[tIndex];
                                    tIndex++;
                                }
                                foreach (var fieldMapperItem in fieldMapperDic)
                                {
                                    //写入标题行
                                    if (currentRawIndex == fileDescription.TitleRawIndex)
                                    {
                                        rawValueArray[fieldMapperItem.Key] = fieldMapperItem.Value.CSVTitle;
                                    }
                                    //真正的数据从标题行下一行开始写
                                    else
                                    {
                                        propertyInfo = fieldMapperItem.Value.PropertyInfo;
                                        object propertyValue = propertyInfo.GetValue(t);
                                        string formatValue = null;
                                        if (propertyValue != null)
                                        {
                                            if (propertyInfo.PropertyType is IFormattable && !string.IsNullOrEmpty(fieldMapperItem.Value.OutputFormat))
                                            {
                                                formatValue = ((IFormattable)propertyValue).ToString(fieldMapperItem.Value.OutputFormat, null);
                                            }
                                            else
                                            {
                                                formatValue = propertyValue.ToString();
                                            }

                                            //如果属性值含有分隔符,则使用双引号包裹
                                            if (formatValue.Contains(fileDescription.SeparatorChar.ToString()))
                                            {
                                                formatValue = $"\"{formatValue}\"";
                                            }
                                            rawValueArray[fieldMapperItem.Key] = formatValue;
                                        }
                                    }
                                }
                                rawValue = string.Join(fileDescription.SeparatorChar, rawValueArray);
                            }
                            rawValueBuilder.Append(rawValue + "\r\n");
                        }
                        catch (Exception e)
                        {
                            string msg = $"(异常)Excel第{currentRawIndex + 1}行,数据列表第{tIndex + 1}个数据写入失败!rawValue:{rawValue}";
                            //this._Logger.LogWarning(e, msg);
                            throw new Exception(msg);
                        }

                        currentRawIndex++;
                    } while (tIndex < dataCount);
                    streamWriter.Write(rawValueBuilder.ToString());

                    streamWriter.Close();
                    streamWriter.Dispose();
                }
            }
        }

    }
}

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace StockCheckApp.Utils
{
    /// <summary>
    /// 字段映射类
    /// </summary>
    public class FieldMapper
    {
        /// <summary>
        /// 属性信息
        /// </summary>
        public PropertyInfo PropertyInfo { get; set; }
        /// <summary>
        /// 标题
        /// </summary>
        public string CSVTitle { get; set; }
        /// <summary>
        /// 标题下标位置
        /// </summary>
        public int CSVTitleIndex { get; set; }
        /// <summary>
        /// 字符输出格式(数字和日期类型需要)
        /// </summary>
        public string OutputFormat { get; set; }

        public static List<FieldMapper> GetModelFieldMapper<T>()
        {
            List<FieldMapper> fieldMapperList = new List<FieldMapper>(100);

            List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList();
            CsvColumnAttribute csvColumnAttribute = null;
            foreach (var tPropertyInfo in tPropertyInfoList)
            {
                csvColumnAttribute = (CsvColumnAttribute)tPropertyInfo.GetCustomAttribute(typeof(CsvColumnAttribute));
                if (csvColumnAttribute != null)
                {
                    fieldMapperList.Add(new FieldMapper
                    {
                        PropertyInfo = tPropertyInfo,
                        CSVTitle = csvColumnAttribute.Title,
                        CSVTitleIndex = csvColumnAttribute.TitleIndex,
                        OutputFormat = csvColumnAttribute.OutputFormat
                    });
                }
            }
            return fieldMapperList;
        }

    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace StockCheckApp.Utils
{
    public class StringHelper
    {
        /// <summary>
        /// 获取字符串中第strPosition个位置的str的下标
        /// </summary>
        /// <param name="text"></param>
        /// <param name="str"></param>
        /// <param name="strPosition"></param>
        /// <returns></returns>
        public static int GetIndexOfStr(string text, string str, int strPosition)
        {
            int strIndex = -1;

            int currentPosition = 0;
            if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(str) && strPosition >= 1)
            {
                do
                {
                    currentPosition++;
                    if (strIndex == -1)
                    {
                        strIndex = text.IndexOf(str);
                    }
                    else
                    {
                        strIndex = text.IndexOf(str, strIndex + 1);
                    }
                } while (currentPosition < strPosition);
            }

            return strIndex;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace StockCheckApp.Utils
{
    /// <summary>
    /// 类型帮助类
    /// </summary>
    public class TypeHelper
    {
        private static Dictionary<Type, List<PropertyInfo>> _TypePropertyDic = new Dictionary<Type, List<PropertyInfo>>(0);

        /// <summary>
        /// 获取T属性列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<PropertyInfo> GetTPropertyDic<T>()
        {
            Type tType = typeof(T);
            List<PropertyInfo> propertyInfoList = null;
            if (TypeHelper._TypePropertyDic.ContainsKey(tType))
            {
                propertyInfoList = TypeHelper._TypePropertyDic[tType];
            }
            else
            {
                propertyInfoList = tType.GetProperties().ToList();
                TypeHelper._TypePropertyDic.Add(tType, propertyInfoList);
            }

            return propertyInfoList;
        }

        /// <summary>
        /// 获取t属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static object GetPropertyValue<T>(T t, string propertyName)
        {
            object value = null;

            Type tType = typeof(T);
            List<PropertyInfo> propertyInfoList = TypeHelper.GetTPropertyDic<T>();

            PropertyInfo propertyInfo = propertyInfoList.FirstOrDefault(m => m.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));

            if (propertyInfo != null)
            {
                value = propertyInfo.GetValue(t);
            }
            return value;
        }

        /// <summary>
        /// 设置t属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        public static void SetPropertyValue<T>(T t, string propertyName, object propertyValue)
        {
            Type tType = typeof(T);
            List<PropertyInfo> propertyInfoList = TypeHelper.GetTPropertyDic<T>();

            PropertyInfo propertyInfo = propertyInfoList.FirstOrDefault(m => m.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));

            if (propertyInfo != null && propertyValue != null)
            {
                if (!propertyInfo.PropertyType.IsGenericType)
                {
                    propertyInfo.SetValue(t, Convert.ChangeType(propertyValue, propertyInfo.PropertyType));
                }
                else
                {
                    Type genericTypeDefinition = propertyInfo.PropertyType.GetGenericTypeDefinition();
                    if (genericTypeDefinition == typeof(Nullable<>))
                    {
                        propertyInfo.SetValue(t, Convert.ChangeType(propertyValue, Nullable.GetUnderlyingType(propertyInfo.PropertyType)));
                    }
                }
            }
        }

        /// <summary>
        /// 克隆相同属性数据到另一个类列表中
        /// </summary>
        /// <typeparam name="Tin"></typeparam>
        /// <typeparam name="Tout"></typeparam>
        /// <param name="inList"></param>
        /// <returns></returns>
        public static List<Tout> CloneData<Tin, Tout>(List<Tin> inList) where Tout : new()
        {
            List<Tout> outList = new List<Tout>(0);

            if (inList != null && inList.Count > 0)
            {
                Dictionary<string, PropertyInfo> inTProList = TypeHelper.GetTPropertyDic<Tin>().ToDictionary(m => m.Name);
                Dictionary<string, PropertyInfo> outTProList = TypeHelper.GetTPropertyDic<Tout>().ToDictionary(m => m.Name);

                Tout outT = default(Tout);
                foreach (var item in inList)
                {
                    outT = new Tout();
                    foreach (var inProItem in inTProList)
                    {
                        if (outTProList.ContainsKey(inProItem.Key))
                        {
                            outTProList[inProItem.Key].SetValue(outT, inProItem.Value.GetValue(item));
                        }
                    }
                    outList.Add(outT);
                }
            }

            return outList;
        }

    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace StockCheckApp.Utils
{
    /// <summary>
    /// Csv文件类特性标记
    /// </summary>
    [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false)]
    public class CsvColumnAttribute : System.Attribute
    {
        internal const int defaultTitleIndex = Int32.MaxValue;
        /// <summary>
        /// 标题
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 标题位置(从0开始)
        /// </summary>
        public int TitleIndex { get; set; }
        /// <summary>
        /// 字符输出格式(数字和日期类型需要)
        /// </summary>
        public string OutputFormat { get; set; }

        public CsvColumnAttribute()
        {
            Title = "";
            TitleIndex = defaultTitleIndex;
            OutputFormat = "";
        }

        public CsvColumnAttribute(string title, int titleIndex, string outputFormat)
        {
            Title = title;
            TitleIndex = titleIndex;
            OutputFormat = outputFormat;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace StockCheckApp.Utils
{
    public class CsvFileDescription
    {
        public CsvFileDescription() : this(0)
        {
        }
        public CsvFileDescription(int titleRawIndex) : this(',', titleRawIndex, Encoding.UTF8)
        {
        }
        public CsvFileDescription(char separatorChar, int titleRawIndex, Encoding encoding)
        {
            this.SeparatorChar = separatorChar;
            this.TitleRawIndex = titleRawIndex;
            this.Encoding = encoding;
        }

        /// <summary>
        /// CSV文件字符编码
        /// </summary>
        public Encoding Encoding { get; set; }

        /// <summary>
        /// 分隔符(默认为(,),也可以是其他分隔符如(\t))
        /// </summary>
        public char SeparatorChar { get; set; }
        /// <summary>
        /// 标题所在行位置(默认为0,没有标题填-1)
        /// </summary>
        public int TitleRawIndex { get; set; }

    }
}

  

using StockCheckApp.Utils;
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;

namespace StockCheckApp.Models
{
    public class GoodsCheckInfo
    {

        /// <summary>
        /// 指示当前对象自创建以来,属性 GoodsCode 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isGoodsCodeSetValue;

        private string _goodsCode;

        /// <summary>
        /// 商品代码
        /// </summary>
        [CsvColumn(Title = "商品代码", TitleIndex = 0, OutputFormat = "")]
        public string GoodsCode
        {
            get
            {
                return this._goodsCode;
            }
            set
            {
                this._goodsCode = value;
                this._isGoodsCodeSetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 LotNo 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isLotNoSetValue;

        private string _lotNo;

        /// <summary>
        /// 批号
        /// </summary>
        [CsvColumn(Title = "批号", TitleIndex = 1, OutputFormat = "")]
        public string LotNo
        {
            get
            {
                return this._lotNo;
            }
            set
            {
                this._lotNo = value;
                this._isLotNoSetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 GoodsQty 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isGoodsQtySetValue;

        private string _goodsQty;

        /// <summary>
        /// 盘点数量
        /// </summary>
        [CsvColumn(Title = "盘点数量", TitleIndex = 2, OutputFormat = "")]
        public string GoodsQty
        {
            get
            {
                return this._goodsQty;
            }
            set
            {
                this._goodsQty = value;
                this._isGoodsQtySetValue = true;
            }
        }

        public bool UpdateTag { get; set; }
    }
}

using StockCheckApp.Utils;
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;

namespace StockCheckApp.Models
{
    public class GoodsInfo
    {

        /// <summary>
        /// 指示当前对象自创建以来,属性 GoodsCode 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isGoodsCodeSetValue;

        private string _goodsCode;

        /// <summary>
        /// 商品编号
        /// </summary>
        [CsvColumn(Title = "商品代码", TitleIndex = 0, OutputFormat = "")]
        public string GoodsCode
        {
            get
            {
                return this._goodsCode;
            }
            set
            {
                this._goodsCode = value;
                this._isGoodsCodeSetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 BarCode1 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isBarCode1SetValue;

        private string _barCode1;

        /// <summary>
        /// 商品条码1
        /// </summary>
        [CsvColumn(Title = "条码1", TitleIndex = 1, OutputFormat = "")]
        public string BarCode1
        {
            get
            {
                return this._barCode1;
            }
            set
            {
                this._barCode1 = value;
                this._isBarCode1SetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 BarCode2 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isBarCode2SetValue;

        private string _barCode2;

        /// <summary>
        /// 商品条码2
        /// </summary>
        [CsvColumn(Title = "条码2", TitleIndex = 2, OutputFormat = "")]
        public string BarCode2
        {
            get
            {
                return this._barCode2;
            }
            set
            {
                this._barCode2 = value;
                this._isBarCode2SetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 BarCode3 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isBarCode3SetValue;

        private string _barCode3;

        /// <summary>
        /// 商品条码3
        /// </summary>
        [CsvColumn(Title = "条码3", TitleIndex = 3, OutputFormat = "")]
        public string BarCode3
        {
            get
            {
                return this._barCode3;
            }
            set
            {
                this._barCode3 = value;
                this._isBarCode3SetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 BarCode4 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isBarCode4SetValue;

        private string _barCode4;

        /// <summary>
        /// 商品条码4
        /// </summary>
        [CsvColumn(Title = "条码4", TitleIndex = 4, OutputFormat = "")]
        public string BarCode4
        {
            get
            {
                return this._barCode4;
            }
            set
            {
                this._barCode4 = value;
                this._isBarCode4SetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 BarCode5 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isBarCode5SetValue;

        private string _barCode5;

        /// <summary>
        /// 商品条码5
        /// </summary>
        [CsvColumn(Title = "条码5", TitleIndex = 5, OutputFormat = "")]
        public string BarCode5
        {
            get
            {
                return this._barCode5;
            }
            set
            {
                this._barCode5 = value;
                this._isBarCode5SetValue = true;
            }
        }

        /// <summary>
        /// 指示当前对象自创建以来,属性 GoodsName 是否已经设置了值(含设置为 null)。
        /// </summary>
        protected bool _isGoodsNameSetValue;

        private string _goodsName;

        /// <summary>
        /// 商品名称(中文)
        /// </summary>
        [CsvColumn(Title = "商品名称", TitleIndex = 6, OutputFormat = "")]
        public string GoodsName
        {
            get
            {
                return this._goodsName;
            }
            set
            {
                this._goodsName = value;
                this._isGoodsNameSetValue = true;
            }
        }
    }
}

使用:
string dirGoodsMst = Directory.GetCurrentDirectory() + "\\DataResource\\GoodsMst.csv";
List<GoodsInfo> GoodsInfos = CsvHelper.getInstance().Read<GoodsInfo>(dirGoodsMst, csvFileDescription);

标签:文件,null,string,读写,System,._,using,CSV,public
From: https://www.cnblogs.com/xsj1989/p/16741846.html

相关文章

  • Windows下文件搜索最佳神器
    你是不是有时候想找一个文件,但只记得文件名的几个字,然后在某个磁盘或目录下漫无目的的搜索,等了十几分钟也没找到你需要的文件?那你应该试试Everything了,一个Windows平台真正......
  • NFC读写器与浏览器Chrome
    随着NFC读写器在BS架构下的需求越来越多,使用JS语言在web浏览器下操作NFC读写器就变得尤其重要.但是web浏览器不允许其显示内容直接操作硬件,所以我们必须使用IC卡读卡器we......
  • log4net 日期和文件大小滚动Composite模式 删除自定义几天前的日志
    官方配置信息Apachelog4net–Apachelog4net:ConfigExamples-Apachelog4net官方示例实现RollingFileAppenderlogging-log4net/DerivedAppender.csat3f2b3......
  • 【git】下载单个文件夹
    https://blog.csdn.net/weixin_40746796/article/details/90262646?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST......
  • 三(二)、映射文件之select返回和resultMap
    目录结构同​​三(一)、mybatis映射文件-增删改和参数处理 ​​​中的​​目录结构​​这里需要再添加一张表:CREATETABLE`tbl_department`(`id`int(11)NOTNULLAUT......
  • 九、springMVC之文件上传
    一、配置方式web.xml:只配置了DispatcherServlet:1<?xmlversion="1.0"encoding="UTF-8"?>2<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"3xml......
  • 迅为RK3568开发板Busybox制作最小文件系统编译busybox
    保存退出之后,我们需要设置临时环境变量如下图所示:exportPATH=/usr/local/arm64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin:$PATH输入“echo$PATH”,查看环......
  • shell脚本之检测文件类型
    1.功能:输入路径,检测文件类型。2.复习:shellwhile循环,if条件语句,file命令使用等。3.代码实现:catfile.sh[root@VM-4-13-centosshell]#catfile.sh#!/bin/bashwhil......
  • 上传到Nginx的图片文件如何拥有可读的权限
    描述使用springmvc做了一个文件上传的功能,上传到nginx目录下的一个文件夹,但是通过目录访问的时候却报403的错误去服务器查看了一下文件的权限,发现没有可读权限,于是定位......
  • Qt小技巧15.Pro文件的床边故事
    1引言这篇文章很简单,小结下Pro文件的那些好用但是又不常用的功能,用好了Pro文件,对开发人员来说那是大有裨益,身体倍儿棒。2说正事2.1定义一个字符串宏例如我想定义一......