如何解决文件名超256的问题

一直以来,以基础中间件开发和产品设计为主,C语言为根本,但随着用户业务的技术特点

  1. 文件存储层次化,多层目录叠加;
  2. 目录、文件名个性化,单个目录或文件名过长;

等因素,造成此前产品中仅仅能支持256个字节(也就是128个汉字)以内的问题,逐渐显现,并成为用户或集成商所累赘或诟病,如何搞定?

调查了一下,也搜罗了网络上的说法,不外乎几种

  1. windows原始函数(如_open、_access等),就是不支持256以上的文件名;
  2. Win32 API接口(如CopyFile、CreateFile等)的Unicode版本(CreateFileW),可以提供32000个宽字节的文件名

如果真是如此,那使用原始C函数的产品或软件,不就惨了吗?不能与时俱进了

那怎么能行!调查后,发现GetShortPathName函数,可以将长文件名进行8.3格式转换,为_open等函数所使用,直白一点,也就是将文件名缩短了,_open等函数就认了。真是的,本是同根(Windows)生,相煎何太急!

经过验证,提供如下函数,可将长文件名缩短,以支持256字节以上的长文件名。有几个要点,要记牢

  1. 被缩短的目录名,必须要存在,否则将不能缩短
  2. 创建深层次目录时,需要从存在的一层开始进行迭代缩短,以保证创建成功
#define WMY_FULL_FILENAME_LEN 512
#if defined(WIN32) || defined(WIN64) || defined(_WIN32_WCE)
void shortedFileName(char *inFileName, char *outFileName)
{
	int sRet = 0;
	WCHAR wLongFilePath[WMY_FULL_FILENAME_LEN+1] = {0};
	WCHAR wShortFilePath[WMY_FULL_FILENAME_LEN+1] = {0};
	char newFilePath[WMY_FULL_FILENAME_LEN+1] = {0};
	char *p = strrchr(inFileName, T_PATHCONNCHR);
	if(p){
		MultiByteToWideChar (CP_ACP, 0, inFileName, p-inFileName, wLongFilePath, WMY_FULL_FILENAME_LEN);
	}
	else{
		MultiByteToWideChar (CP_ACP, 0, inFileName, -1, wLongFilePath, WMY_FULL_FILENAME_LEN);
	}
	sRet = GetShortPathNameW(wLongFilePath, wShortFilePath, WMY_FULL_FILENAME_LEN);
	if(0!=sRet)
	{
		WideCharToMultiByte(CP_OEMCP,NULL,wShortFilePath,-1,newFilePath,WMY_FULL_FILENAME_LEN,NULL,FALSE);
	}
	else{
		WideCharToMultiByte(CP_OEMCP,NULL,wLongFilePath,-1,newFilePath,WMY_FULL_FILENAME_LEN,NULL,FALSE);
	}
	if(p)
		sprintf(outFileName, "%s%c%s", newFilePath, T_PATHCONNCHR, p+1);
	else
		sprintf(outFileName, "%s", newFilePath);
}
#endif

附录参考:

GetShortPathName

The GetShortPathName function retrieves the short path form of a specified input path.

DWORD GetShortPathName(
  LPCTSTR lpszLongPath,  // null-terminated path string
  LPTSTR lpszShortPath,  // short form buffer
  DWORD cchBuffer        // size of short form buffer
);

Parameters

lpszLongPath
[in] Pointer to a null-terminated path string. The function retrieves the short form of this path.

Windows NT/2000/XP: In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to nearly 32,000 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. For more
information, see File Name Conventions.

Windows 95/98/Me: This string must not exceed MAX_PATH characters.

lpszShortPath
[out] Pointer to a buffer to receive the null-terminated short form of the path specified bylpszLongPath.
cchBuffer
[in] Specifies the size, in TCHARs, of the buffer pointed to bylpszShortPath.

Return Values

If the function succeeds, the return value is the length, in TCHARs, of the string copied tolpszShortPath, not including the terminating null character.

If the lpszShortPath buffer is too small to contain the path, the return value is the size of the buffer, inTCHARs, required to hold the path. Therefore, if the return value is greater thancchBuffer, call the function again
with a buffer that is large enough to hold the path.

If the function fails for any other reason, the return value is zero. To get extended error information, callGetLastError.

Remarks

When an application calls this function and specifies a path on a volume that does not support 8.3 aliases, the function fails with ERROR_INVALID_PARAMETER if the path is longer than 67 bytes.

The path specified by lpszLongPath does not have to be a full or a long path. The short form may be longer than the specifed path.

If the specified path is already in its short form, there is no need for any conversion, and the function simply copies the specified path to the buffer for the short path.

You can set lpszShortPath to the same value as lpszLongPath; in other words, you can set the buffer for the short path to the address of the input path string.

You can obtain the long name of a file from the short name by calling the GetLongPathName function. Alternatively, where GetLongPathName is not available, you can callFindFirstFile on each component of the path to get the corresponding
long name.

Windows 95/98/Me: GetShortPathNameW is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined inMicrosoft Layer for Unicode on Windows
95/98/Me Systems.

Requirements

  Windows NT/2000/XP: Included in Windows NT 3.5 and later.

  Windows 95/98/Me: Included in Windows 95 and later.

  Header: Declared in Winbase.h; include Windows.h.

  Library: Use Kernel32.lib.

  Unicode: Implemented as Unicode and ANSI versions on Windows NT/2000/XP. Also supported by Microsoft Layer for Unicode.

See Also

File I/O Overview, File I/O Functions,FindFirstFile,
GetFullPathName, GetLongPathName,SetFileShortName

老树(老产品)开新花,就看如何对待了。

欢迎感兴趣的,提供相关的产品解决之道,提高产品的应用范围和效益,延长生命周期,降低成本。

时间: 2024-07-31 13:55:46

如何解决文件名超256的问题的相关文章

asp.net 文件下载 解决文件名乱码

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; using ElementLibrary.BLL; using ElementLibrary.MODEL; using System.Text; /* * LiuH * Descr:下载处理DownLoadFile.ashx * Addtime:2014/8/26 * LastModifyTim

利用php CI force_download($filename, $data) 下载.csv 文件解决文件名乱码,文件内容乱码

利用php CI force_download($filename, $data) 下载.csv 文件解决文件名乱码,文件内容乱码.做了很久终于知道了很好的解决方案. 1.加载辅助函数 $this->load->helper('download'); //下载辅助函数 $this->load->helper('string'); //字符编码转换辅助翻书 2.force_download($filename, $data)通过它的代码可以知道$data 必须是字符串,如果不是字符串

java基础--->文件--->从标准输入读取字符串作为文件名---->解决“文件名乱码”问题

概述:程序中有时会需要从标准输入读取字符串作为文件的名字,其具体实现方法有许多种.我第一次尝试编写这方面的程序时遇到了"乱码问题",后来使用了新的写法解决了乱码问题. /*原码,使用这种方法编写的代码会出现"乱码问题" 乱码原因分析:从标准输入读取的数据先被存放至byte[]中,之后又将byte数组转成String,这个过程中就会出现编码不一致的问题 如标准输入"file1",但是最终fileName=buffer.toString()的结果却是

PHP中调用SVN命令更新网站方法(解决文件名包含中文更新失败的问题)

想说写一个通过网页就可以执行 SVN 升级的程序,结果并不是我想得那样简单,有一些眉角需要注意的说. 先以 Apache 的用户帐号执行 SVN checkout,这样 Apache 才有 SVN 的链结权力,才可以通过网页执行 SVN update su -s /bin/bash www-data cd /var/www svn checkout http://www.xxx.com/svn/my_site 在用 PHP 执行 shell 指令前要加上 export LANG=C.UTF-8

如何解决秒杀的性能问题和超卖的讨论

如何解决秒杀的性能问题和超卖的讨论 最近业务试水电商,接了一个秒杀的活.之前经常看到淘宝的同行们讨论秒杀,讨论电商,这次终于轮到我们自己理论结合实际一次了. ps:进入正文前先说一点个人感受,之前看淘宝的ppt感觉都懂了,等到自己出解决方案的时候发现还是有很多想不到的地方其实都没懂,再次验证了“细节是魔鬼”的理论.并且一个人的能力有限,只有大家一起讨论才能想的更周全,更细致.好了,闲话少说,下面进入正文. 一.秒杀带来了什么? 秒杀或抢购活动一般会经过[预约][抢订单][支付]这3个大环节,而其

解决redis秒杀超卖的问题

我们再使用redis做秒杀程序的时候,解决超卖问题,是重中之重.以下是一个思路. 用上述思路去做的话,我们再用户点击秒杀的时候,只需要检测,kucun_count中是否能pop出数据,如果能pop出来则证明还有库存,且秒杀成功.而且pop是原子性的,即使很高的并发, 同时有很多用户访问,也是排队一个一个解决(并行转串行). 这样的话,就解决了超卖的问题.至于存入磁盘,我的上一篇文章中有介绍.有需要的朋友可以去看. 这是一个思路,具体的秒杀程序应该还有很多细节需要完善,但是核心问题已经解决了哈.

秒杀与超卖的 性能解决之路

一.秒杀带来了什么? 秒杀或抢购活动一般会经过[预约][抢订单][支付]这3个大环节,而其中[抢订单] 这个环节是最考验业务提供方的抗压能力的. 抢订单环节一般会带来2个问题: 1.高并发 比较火热的秒杀在线人数都是10w起的,如此之高的在线人数对于 网站架构从前到后都是一种考验. 2.超卖 任何商品都会有数量上限,如何避免成功下订单买到商品的人数不 超过商品数量的上限,这是每个抢购活动都要面临的难题. 二.如何解决? 首先,产品解决方案我们就不予讨论了.我们只讨论技术解决方案 1.前端 面对高

解决phpexcel保存时文件命中文出现 乱码 (这个真的有用)

Phpexcel导出Excel文件时有两个主要的过程: 1.定义文件名 2.填充Excel数据 这两个过程中可能会出现一些乱码问题,下面我来说一下解决办法: 解决文件名的乱码: 乱码原因:客户使用的中文版Windows系统平台,而Windows平台的文件名编码为gb2312(gbk),而我们网页编码为了跟进现存潮流 一般都采用utf-8(国际化)编码,这时当我们:header("Content-Disposition: inline; filename=\"" . $file

java 获取文件名时乱码

1,文件乱码的原因: 这还要提起,之前工作中一位领导的开导.本质原因就是你要读取的内容的编码与你读取使用的编码不一致导致读取的乱码. 保证不乱码,需要在读取的时候设置与内容一致的编码格式. 2,获取取文件名乱码解读: File.getName() 获取文件名的时候,是根据JDK的默认文件编码进行获取的.要查看JDK中文件的默认编码可以通过Sytem.getProperties().get("file.encoding"); 进行查看. 3,解决文件名读取乱码: //获取系统的默认编码,